Skip to content

Commit

Permalink
Update Docker push commands and add checks for App properties (#149)
Browse files Browse the repository at this point in the history
* - Updated commands for pushing docker image
- Added code to wait for App properties

* wait for sp and sp property creation

Co-authored-by: Glenn Musa <4622125+glennmusa@users.noreply.github.com>
  • Loading branch information
Phydeauxman and glennmusa authored Apr 13, 2021
1 parent 4866c9b commit 86022b2
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 64 deletions.
118 changes: 64 additions & 54 deletions src/scripts/config/mlz_config_create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,46 +20,6 @@ usage() {
error_log "usage: mlz_config_create.sh <mlz config>"
}

sp_exists () {

sp_name=$1
sp_property=$2

sp_query="az ad sp show \
--id http://${sp_name} \
--query ${sp_property}"

if ! $sp_query &> /dev/null; then

sleep_time_in_seconds=10
max_wait_in_minutes=3
max_wait_in_seconds=180
max_retries=$((max_wait_in_seconds/sleep_time_in_seconds))

echo "INFO: maximum time to wait in seconds = ${max_wait_in_seconds}"
echo "INFO: maximum number of retries = ${max_retries}"

count=1

while ! $sp_query &> /dev/null
do

echo "INFO: waiting for service principal ${sp_name} to populate property ${sp_property} (${count}/${max_retries})"
echo "INFO: trying again in ${sleep_time_in_seconds} seconds..."
sleep "${sleep_time_in_seconds}"

if [[ ${count} -eq max_retries ]]; then
error_log "ERROR: unable to determine ${sp_property} for the service principal ${sp_property} in ${max_wait_in_minutes} minutes. Investigate and re-run script."
exit 1
fi

count=$((count +1))

done
fi

}

if [[ "$#" -lt 1 ]]; then
usage
exit 1
Expand Down Expand Up @@ -93,6 +53,64 @@ do
fi
done

# accomodate for transient behavior where Service Principal is created
# but an immediate query for it will fail
# and attempt for max_wait_in_seconds before giving up.
wait_for_sp_creation() {
sp_name=$1
sp_query="az ad sp show --id ${sp_name}"

sleep_time_in_seconds=10
max_wait_in_seconds=180
max_retries=$((max_wait_in_seconds/sleep_time_in_seconds))

count=1

while ! $sp_query &> /dev/null
do
echo "INFO: waiting for service principal ${sp_name} to come back from query '${sp_query}' (${count}/${max_retries})..."
echo "INFO: trying again in ${sleep_time_in_seconds} seconds..."
sleep "${sleep_time_in_seconds}"

if [[ ${count} -eq max_retries ]]; then
error_log "ERROR: unable to retrieve the service principal ${sp_name} from query '${sp_query}' in ${max_wait_in_seconds} seconds. Investigate and re-run script."
exit 1
fi

count=$((count +1))
done
}

# accomodate for transient behavior where Service Principal is created
# but an immediate query for its properties will fail
# and attempt for max_wait_in_seconds before giving up.
wait_for_sp_property() {
sp_name=$1
sp_property=$2

query="az ad sp show --id ${sp_name} --query ${sp_property} --output tsv"

sleep_time_in_seconds=10
max_wait_in_seconds=180
max_retries=$((max_wait_in_seconds/sleep_time_in_seconds))

count=1

while [[ -z $($query) ]]
do
echo "INFO: waiting for query \"${query}\" to return results (${count}/${max_retries})"
echo "INFO: trying again in ${sleep_time_in_seconds} seconds..."
sleep "${sleep_time_in_seconds}"

if [[ ${count} -eq max_retries ]]; then
error_log "ERROR: unable to get results from query \"${query}\" in ${max_wait_in_seconds} seconds. Investigate and re-run script."
exit 1
fi

count=$((count +1))
done
}

# Create Azure AD application registration and Service Principal
# TODO: Lift the subscription scoping out of here and move into conditional
echo "INFO: verifying service principal ${mlz_sp_name} is unique..."
Expand All @@ -105,22 +123,14 @@ if [[ -z $(az ad sp list --filter "displayName eq '${mlz_sp_name}'" --query "[].
--only-show-errors \
--output tsv)

# Get Service Principal AppId
# Added the sleep below to accomodate for the transient behavior where the Service Principal creation
# is complete but an immediate query for it will fail. The sleep loop will run for 3 minutes and then
# the script will exit due to a platform problem
sp_exists "${mlz_sp_name}" "appId"
wait_for_sp_creation "http://${mlz_sp_name}"
wait_for_sp_property "http://${mlz_sp_name}" "appId"
wait_for_sp_property "http://${mlz_sp_name}" "objectId"

sp_clientid=$(az ad sp show \
--id "http://${mlz_sp_name}" \
--query appId \
--output tsv)

# Get Service Principal ObjectId
# Added the sleep below to accomodate for the transient behavior where the Service Principal creation
# is complete but an immediate query for it will fail. The sleep loop will run for 3 minutes and then
# the script will exit due to a platform problem
sp_exists "${mlz_sp_name}" "objectId"
--id "http://${mlz_sp_name}" \
--query appId \
--output tsv)

sp_objid=$(az ad sp show \
--id "http://${mlz_sp_name}" \
Expand Down
48 changes: 41 additions & 7 deletions src/scripts/container-registry/add_auth_scopes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,51 @@ required_resources_json_file="$(dirname "$(realpath "${BASH_SOURCE%/*}")")/confi

# generate app registration
echo "INFO: creating app registration ${mlz_fe_app_name} to facilitate user logon at ${fqdn}..."
client_id=$(az ad app create \
az ad app create \
--display-name "${mlz_fe_app_name}" \
--reply-urls "http://${fqdn}/redirect" \
--required-resource-accesses "${required_resources_json_file}" \
--query appId \
--output tsv)
client_password=$(az ad app credential reset \
--id ${client_id} \
--query password \
--only-show-errors \
--output tsv)
--output none

# wait_for_query_success will attempt the query passed by argument
# if the query does not return a result within max_wait_in_seconds it will exit.
wait_for_query_success() {
query=$1

sleep_time_in_seconds=10
max_wait_in_seconds=180
max_retries=$((max_wait_in_seconds/sleep_time_in_seconds))

count=1

while [[ -z $($query) ]]
do
echo "INFO: waiting for query \"${query}\" to return results (${count}/${max_retries})"
echo "INFO: trying again in ${sleep_time_in_seconds} seconds..."
sleep "${sleep_time_in_seconds}"

if [[ ${count} -eq max_retries ]]; then
error_log "ERROR: unable to get results from query \"${query}\" in ${max_wait_in_seconds} seconds. Investigate and re-run script."
exit 1
fi

count=$((count +1))
done
}

# use `wait_for_query_success` to accomodate transient failures where
# app creation completes but an immediate query for it will fail
app_id_query="az ad app list --display-name ${mlz_fe_app_name} --query [].appId --output tsv"
wait_for_query_success "$app_id_query"

client_id=$($app_id_query)

client_password=$(az ad app credential reset \
--id ${client_id} \
--query password \
--only-show-errors \
--output tsv)

# update keyvault with the app registration information
echo "INFO: storing app registration information for client ID ${client_id} in ${mlz_kv_name}..."
Expand Down
5 changes: 2 additions & 3 deletions src/scripts/setup_ezdeploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ usage() {
timestamp=$(date +%s)

metadata_host="management.azure.com" # TODO (20210401): pass this by parameter or derive from cloud
acr_endpoint="azurecr.io" # TODO (20210401): pass this by parameter or derive from cloud

# set helpful defaults that can be overridden or 'notset' for mandatory input
docker_strategy="build"
Expand Down Expand Up @@ -166,8 +165,8 @@ if [[ $docker_strategy == "load" ]]; then
docker load -i mlz.tar
fi

docker tag "${image_name}:${image_tag}" "${mlz_acr_name}.${acr_endpoint}/${image_name}:${image_tag}"
docker push "${mlz_acr_name}.${acr_endpoint}/${image_name}:${image_tag}"
docker tag "${image_name}:${image_tag}" "${mlz_acr_name}${mlz_acrLoginServerEndpoint}/${image_name}:${image_tag}"
docker push "${mlz_acr_name}${mlz_acrLoginServerEndpoint}/${image_name}:${image_tag}"

# deploy an instance
"${container_registry_path}/deploy_instance.sh" "$mlz_config_file" "$image_name" "$image_tag"
Expand Down

0 comments on commit 86022b2

Please sign in to comment.