From fa79725f5f78f3032b24f86ef9165ebf6fa4d1a4 Mon Sep 17 00:00:00 2001 From: lolorol Date: Sat, 2 Jul 2022 09:03:09 +0000 Subject: [PATCH] Fix for github bootstrap --- scripts/lib/aad_constants.sh | 4 ++ scripts/lib/azure_ad.sh | 91 ++++++++++++++++++++++++++++++------ scripts/lib/bootstrap.sh | 7 ++- 3 files changed, 83 insertions(+), 19 deletions(-) diff --git a/scripts/lib/aad_constants.sh b/scripts/lib/aad_constants.sh index cee43e5e..f9903cee 100644 --- a/scripts/lib/aad_constants.sh +++ b/scripts/lib/aad_constants.sh @@ -1,5 +1,9 @@ declare -A roleTemplate=( ['Global Administrator']='62e90394-69f5-4237-9190-012177145e10' + ['Privileged Role Administrator']='e8611ab8-c189-46e8-94e1-60213ab1f814' + ['Application Administrator']='9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3' + ['Groups Administrator']='fdd7a751-b60b-444a-984c-02652fe8fa1c' + ['Directory Readers']='88d8e3e3-8f55-4a1e-953a-9b9898b8876b' ) declare -A apiPermissions=( diff --git a/scripts/lib/azure_ad.sh b/scripts/lib/azure_ad.sh index 14b0dc73..dd3ac95e 100644 --- a/scripts/lib/azure_ad.sh +++ b/scripts/lib/azure_ad.sh @@ -1,3 +1,4 @@ +microsoft_graph_endpoint=$(az cloud show | jq -r ".endpoints.microsoftGraphResourceId") get_logged_in_user_object_id() { debug "@calling get_logged_in_user_object_id" @@ -21,6 +22,7 @@ create_federated_identity() { if [ "${app}" = "[]" ]; then information "Application ${1}:" + az rest --method post --url "/providers/Microsoft.Authorization/elevateAccess?api-version=2016-07-01" # Create Azure AD application app=$(az ad app create --display-name "${appName}" --only-show-errors) @@ -37,13 +39,17 @@ create_federated_identity() { export app_object_id=$(echo ${app} | jq -r ".id") sp_client_id=$(echo ${sp} | jq -r ".appId") - sp_object_id=$(echo ${sp} | jq -r ".id") + export sp_object_id=$(echo ${sp} | jq -r ".id") if [ ! -z ${gitops_pipelines} ]; then register_gitops_secret ${gitops_pipelines} "AZURE_CLIENT_ID" ${sp_client_id} register_gitops_secret ${gitops_pipelines} "AZURE_OBJECT_ID" ${app_object_id} register_gitops_secret ${gitops_pipelines} "AZURE_TENANT_ID" ${tenant_id} fi + + manage_sp_to_role "Privileged Role Administrator" ${sp_object_id} "POST" + manage_sp_to_role "Application Administrator" ${sp_object_id} "POST" + manage_sp_to_role "Groups Administrator" ${sp_object_id} "POST" else success " - application already created." @@ -51,14 +57,14 @@ create_federated_identity() { app=$(az ad app list --filter "displayname eq '${appName}'" -o json --only-show-errors) && debug "app: ${app}" sp=$(az ad sp list --filter "DisplayName eq '${appName}'" --only-show-errors) && debug "sp: ${sp}" - export app_object_id=$(echo ${app} | jq -r ".[0].id") - sp_client_id=$(echo ${app} | jq -r ".[0].appId") - sp_object_id=$(echo ${sp} | jq -r ".[0].id") + export app_object_id=$(echo ${app} | jq -r ".[0].id") && information "app_object_id: ${app_object_id}" + export sp_client_id=$(echo ${app} | jq -r ".[0].appId") && information "sp_client_id: ${sp_client_id}" + export sp_object_id=$(echo ${sp} | jq -r ".[0].id") && information "sp_object_id: ${sp_object_id}" if [ ! -z ${gitops_pipelines} ]; then register_gitops_secret ${gitops_pipelines} "AZURE_CLIENT_ID" ${sp_client_id} - register_gitops_secret ${gitops_pipelines} "AZURE_OBJECT_ID" ${app_object_id} + register_gitops_secret ${gitops_pipelines} "AZURE_OBJECT_ID" ${sp_object_id} register_gitops_secret ${gitops_pipelines} "AZURE_TENANT_ID" ${tenant_id} fi @@ -66,15 +72,6 @@ create_federated_identity() { if [ ! -z ${gitops_pipelines} ]; then create_gitops_federated_credentials ${gitops_pipelines} ${appName} - - scope="/subscriptions/${sub_management:=$(az account show --query id -o tsv)}" - information "Granting Reader role to ${appName} on ${scope}" - az role assignment create \ - --role "Reader" \ - --assignee-object-id ${sp_object_id} \ - --assignee-principal-type ServicePrincipal \ - --scope ${scope} \ - --only-show-errors fi } @@ -96,4 +93,68 @@ function create_federated_credentials { information "Federated tokens up-to-date for '${2}'." fi -} \ No newline at end of file +} + + + +function enable_directory_role { + # Verify the AD_ROLE_NAME has been activated in the directory + # Permissions required - https://docs.microsoft.com/en-us/graph/api/directoryrole-post-directoryroles?view=graph-rest-1.0&tabs=http#permissions + + AD_ROLE_NAME=${1} + + information "Enabling directory role: ${AD_ROLE_NAME}" + ROLE_ID=$(az rest --method Get --uri ${microsoft_graph_endpoint}v1.0/directoryRoleTemplates -o json | jq -r '.value[] | select(.displayName == "'"$(echo ${AD_ROLE_NAME})"'") | .id') + + URI="${microsoft_graph_endpoint}v1.0/directoryRoles" + + JSON=$( jq -n \ + --arg role_id ${ROLE_ID} \ + '{"roleTemplateId": $role_id}' ) && echo " - body: $JSON" + + + az rest --method POST --uri $URI --header Content-Type=application/json --body "$JSON" + +} + +function manage_sp_to_role() { + + AD_ROLE_NAME=${1} + SERVICE_PRINCIPAL_OBJECT_ID=${2} + METHOD=${3} + echo "Directory role '${AD_ROLE_NAME}'" + + + # Add service principal to AD Role + + export ROLE_AAD=$(az rest --method Get --uri ${microsoft_graph_endpoint}v1.0/directoryRoles -o json | jq -r '.value[] | select(.displayName == "'"$(echo ${AD_ROLE_NAME})"'") | .id') + + if [ "${ROLE_AAD}" == '' ]; then + enable_directory_role + export ROLE_AAD=$(az rest --method Get --uri ${microsoft_graph_endpoint}v1.0/directoryRoles -o json | jq -r '.value[] | select(.displayName == "'"$(echo ${AD_ROLE_NAME})"'") | .id') + fi + + # az rest --method Get --uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments?$filter=principalId+eq+'e72ea7c1-82cd-4f45-8680-41052872763e'" + + + case "${METHOD}" in + POST) + URI=$(echo "${microsoft_graph_endpoint}v1.0/directoryRoles/${ROLE_AAD}/members/\$ref") && echo " - uri: $URI" + + # grant AAD role to the AAD APP + JSON=$( jq -n \ + --arg uri_role "${microsoft_graph_endpoint}v1.0/directoryObjects/${SERVICE_PRINCIPAL_OBJECT_ID}" \ + '{"@odata.id": $uri_role}' ) && echo " - body: $JSON" + + az rest --method ${METHOD} --uri $URI --header Content-Type=application/json --body "$JSON" + + information "Role '${AD_ROLE_NAME}' assigned to azure ad principal" + ;; + DELETE) + URI=$(echo "${microsoft_graph_endpoint}v1.0/directoryRoles/${ROLE_AAD}/members/${SERVICE_PRINCIPAL_OBJECT_ID}/\$ref") && echo " - uri: $URI" + az rest --method ${METHOD} --uri ${URI} || true + information "Role '${AD_ROLE_NAME}' unassigned to azure ad principal ${SERVICE_PRINCIPAL_OBJECT_ID}" + ;; + esac + +} diff --git a/scripts/lib/bootstrap.sh b/scripts/lib/bootstrap.sh index 654a1cfd..89c7eb2a 100644 --- a/scripts/lib/bootstrap.sh +++ b/scripts/lib/bootstrap.sh @@ -27,7 +27,7 @@ bootstrap() { if [ ! -z ${bootstrap_script} ]; then register_rover_context - ${bootstrap_script} "topology_file=${caf_ignite_playbook}" "GITOPS_SERVER_URL=${GITOPS_SERVER_URL}" "RUNNER_NUMBERS=${gitops_number_runners}" "AGENT_TOKEN=${AGENT_TOKEN}" "gitops_agent=${gitops_agent_pool_type}" "ROVER_AGENT_DOCKER_IMAGE=${ROVER_AGENT_DOCKER_IMAGE}" "AZURE_OBJECT_ID=${app_object_id}" "subscription_deployment_mode=${subscription_deployment_mode}" "sub_management=${sub_management}" "sub_connectivity=${sub_connectivity}" "sub_identity=${sub_identity}" "sub_security=${sub_security}" "gitops_pipelines=${gitops_pipelines}" + ${bootstrap_script} "topology_file=${caf_ignite_playbook}" "GITOPS_SERVER_URL=${GITOPS_SERVER_URL}" "RUNNER_NUMBERS=${gitops_number_runners}" "AGENT_TOKEN=${AGENT_TOKEN}" "gitops_agent=${gitops_agent_pool_type}" "ROVER_AGENT_DOCKER_IMAGE=${ROVER_AGENT_DOCKER_IMAGE}" "subscription_deployment_mode=${subscription_deployment_mode}" "sub_management=${sub_management}" "sub_connectivity=${sub_connectivity}" "sub_identity=${sub_identity}" "sub_security=${sub_security}" "gitops_pipelines=${gitops_pipelines}" "TF_VAR_environment=${TF_VAR_environment}" "bootstrap_sp_object_id=${sp_object_id}" fi information "Done." @@ -110,9 +110,6 @@ register_rover_context() { GIT_URL=$(git remote get-url origin) register_gitops_secret ${gitops_pipelines} "ROVER_AGENT_DOCKER_IMAGE" ${ROVER_AGENT_DOCKER_IMAGE} - register_gitops_secret ${gitops_pipelines} "CAF_ENVIRONMENT" ${TF_VAR_environment} - register_gitops_secret ${gitops_pipelines} "CAF_TERRAFORM_LZ_REF" ${GIT_REFS##*/} - register_gitops_secret ${gitops_pipelines} "CAF_TERRAFORM_LZ_URL" ${GIT_URL} register_gitops_secret ${gitops_pipelines} "CAF_GITOPS_TERRAFORM_BACKEND_TYPE" ${gitops_terraform_backend_type} register_gitops_secret ${gitops_pipelines} "CAF_BACKEND_TYPE_HYBRID" ${backend_type_hybrid} register_gitops_secret ${gitops_pipelines} "RUNNER_REGISTRATION_TOKEN" ${AGENT_TOKEN} @@ -167,7 +164,9 @@ create_gitops_federated_credentials() { "github") debug "github" create_federated_credentials "github-${git_project}-pull_request" "repo:${git_org_project}:pull_request" "${2}" + create_federated_credentials "github-${git_project}-refs-heads-main" "repo:${git_org_project}:ref:refs/heads/main" "${2}" create_federated_credentials "github-${git_project}-refs-heads-bootstrap" "repo:${git_org_project}:ref:refs/heads/bootstrap" "${2}" + create_federated_credentials "github-${git_project}-refs-heads-bootstrap" "repo:${git_org_project}:ref:refs/heads/end2end" "${2}" ;; *) echo "Create a federated secret not supported yet for ${1}. You can submit a pull request"