diff --git a/README.md b/README.md index ac0d145..9419afb 100644 --- a/README.md +++ b/README.md @@ -159,9 +159,6 @@ bash scripts/create-service-principal.sh # Configure GitHub secrets bash scripts/configure-github-secrets.sh - -# Add permissions to the service principal -bash scripts/add-permissions-to-service-principal.sh ``` - [Authenticating using a Service Principal and OpenID Connect](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/guides/service_principal_oidc) diff --git a/infra/scenarios/configure_github_secrets/README.md b/infra/scenarios/configure_github_secrets/README.md index fdf962c..070f28d 100644 --- a/infra/scenarios/configure_github_secrets/README.md +++ b/infra/scenarios/configure_github_secrets/README.md @@ -12,7 +12,7 @@ cd infra # Set the variables CREATE_GITHUB_REPOSITORY=false -ENVIRONMENT=ci +ENVIRONMENT=tf APPLICATION_ID=$(az ad sp list --display-name "baseline-environment-on-azure-terraform_$ENVIRONMENT" --query "[0].appId" --output tsv) SUBSCRIPTION_ID=$(az account show --query id --output tsv) diff --git a/infra/scenarios/create_service_principal/README.md b/infra/scenarios/create_service_principal/README.md new file mode 100644 index 0000000..e87a01f --- /dev/null +++ b/infra/scenarios/create_service_principal/README.md @@ -0,0 +1,33 @@ +# Create Service Principal + +This is a scenario for creating a service principal in Microsoft Entra ID. + +## Deploy resources + +```shell +# Go to the infra directory +cd infra + +# Set scenario name +SCENARIO="create_service_principal" + +# Log in to Azure +az login + +# (Optional) Confirm the details for the currently logged-in user +az ad signed-in-user show + +# Set environment variables +export ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) +export TF_VAR_service_principal_name="baseline-environment-on-azure-terraform_tf" + +# Deploy infrastructure +make deploy SCENARIO=$SCENARIO + +# Get output variables +cd scenarios/$SCENARIO +application_object_id=$(terraform output -raw application_object_id) + +# Grant permissions to the application +az ad app permission admin-consent --id $application_object_id +``` diff --git a/infra/scenarios/create_service_principal/main.tf b/infra/scenarios/create_service_principal/main.tf new file mode 100644 index 0000000..e5e5917 --- /dev/null +++ b/infra/scenarios/create_service_principal/main.tf @@ -0,0 +1,78 @@ +terraform { + required_version = ">= 1.6.0" + required_providers { + azuread = { + source = "hashicorp/azuread" + version = "~> 3.0.2" + } + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.5.0" + } + } +} + +provider "azurerm" { + features {} +} + +data "azurerm_subscription" "primary" { +} + +data "azuread_client_config" "client_config" { +} + +data "azuread_application_published_app_ids" "well_known" { +} + +data "azuread_service_principal" "msgraph" { + client_id = data.azuread_application_published_app_ids.well_known.result["MicrosoftGraph"] +} + +resource "azuread_application" "application" { + display_name = var.service_principal_name + owners = [ + data.azuread_client_config.client_config.object_id, + ] + required_resource_access { + resource_app_id = data.azuread_application_published_app_ids.well_known.result["MicrosoftGraph"] + resource_access { + id = data.azuread_service_principal.msgraph.app_role_ids["Domain.Read.All"] + type = "Role" + } + resource_access { + id = data.azuread_service_principal.msgraph.app_role_ids["Group.ReadWrite.All"] + type = "Role" + } + resource_access { + id = data.azuread_service_principal.msgraph.app_role_ids["GroupMember.ReadWrite.All"] + type = "Role" + } + resource_access { + id = data.azuread_service_principal.msgraph.app_role_ids["User.ReadWrite.All"] + type = "Role" + } + resource_access { + id = data.azuread_service_principal.msgraph.app_role_ids["Application.ReadWrite.All"] + type = "Role" + } + } +} + +resource "azuread_service_principal" "service_principal" { + client_id = azuread_application.application.client_id + app_role_assignment_required = false + owners = [ + data.azuread_client_config.client_config.object_id, + ] +} + +resource "azurerm_role_assignment" "role_assignment_service_principal" { + scope = data.azurerm_subscription.primary.id + role_definition_name = var.role_definition_name + principal_id = azuread_service_principal.service_principal.object_id +} + +resource "azuread_service_principal_password" "service_principal_password" { + service_principal_id = azuread_service_principal.service_principal.id +} diff --git a/infra/scenarios/create_service_principal/outputs.tf b/infra/scenarios/create_service_principal/outputs.tf new file mode 100644 index 0000000..83d6496 --- /dev/null +++ b/infra/scenarios/create_service_principal/outputs.tf @@ -0,0 +1,19 @@ +output "service_principal_client_id" { + value = azuread_service_principal.service_principal.client_id + description = "Service Principal Client ID" +} + +output "application_object_id" { + value = azuread_application.application.object_id + description = "Application Object ID" +} + +output "tenant_id" { + value = data.azuread_client_config.client_config.tenant_id + description = "Tenant ID" +} + +output "service_principal_password" { + value = azuread_service_principal_password.service_principal_password.value + sensitive = true +} diff --git a/infra/scenarios/create_service_principal/variables.tf b/infra/scenarios/create_service_principal/variables.tf new file mode 100644 index 0000000..bcc9865 --- /dev/null +++ b/infra/scenarios/create_service_principal/variables.tf @@ -0,0 +1,11 @@ +variable "service_principal_name" { + description = "Specifies the service principal name" + type = string + default = "baseline-environment-on-azure-terraform_ci" +} + +variable "role_definition_name" { + description = "Specifies the role definition name" + type = string + default = "Contributor" +} diff --git a/scripts/add-permissions-to-service-principal.sh b/scripts/add-permissions-to-service-principal.sh deleted file mode 100644 index dd36e03..0000000 --- a/scripts/add-permissions-to-service-principal.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -# for debugging, use `set -eux` instead of `set -eu` -set -eu - -# verify the Azure CLI is installed -if ! command -v az > /dev/null 2>&1; then - echo "Azure CLI is not installed. Please install it first." - echo "https://docs.microsoft.com/cli/azure/install-azure-cli" - exit 1 -fi - -# type the name of the application -echo "Enter the name of the application: (e.g. 'baseline-environment-on-azure-terraform_ci')" -printf "APP_NAME=" -read -r APP_NAME - -echo "Are you sure you want to add permissions to the following service principal?" -echo "> APP_NAME: $APP_NAME" - -# type `y` to proceed -printf "Do you want to proceed? [y/N]: " -read -r response -if [ "$response" != "y" ]; then - echo "Operation aborted." - exit 1 -fi - -# Azure sign in -az login - -# Confirm the details for the currently logged-in user -az ad signed-in-user show - -APPLICATION_ID=$(az ad sp list --display-name "$APP_NAME" --query "[0].appId" --output tsv) -MICROSOFT_GRAPH_API_ID="00000003-0000-0000-c000-000000000000" - -# Add permissions to the service principal for Microsoft Graph API -# Domain.Read.All, Group.ReadWrite.All, GroupMember.ReadWrite.All, User.ReadWrite.All, Application.ReadWrite.All -PERMISSIONS="dbb9058a-0e50-45d7-ae91-66909b5d4664 62a82d76-70ea-41e2-9197-370581804d09 dbaae8cf-10b5-4b86-a4a1-f871c94c6695 741f803b-c850-494e-b5df-cde7c675a1ca 1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9" - -for permission in $PERMISSIONS; do - az ad app permission add \ - --id $APPLICATION_ID \ - --api $MICROSOFT_GRAPH_API_ID \ - --api-permissions $permission=Role -done - -# grant admin consent -az ad app permission admin-consent --id $APPLICATION_ID diff --git a/scripts/configure-github-secrets.sh b/scripts/configure-github-secrets.sh index 038233d..a0b8bd9 100644 --- a/scripts/configure-github-secrets.sh +++ b/scripts/configure-github-secrets.sh @@ -46,6 +46,9 @@ if [ "$response" != "y" ]; then exit 1 fi +# (Optional) Azure sign in +# gh auth login + # Create a new environment # https://github.com/cli/cli/issues/5149 # https://stackoverflow.com/a/71388564/4457856 diff --git a/scripts/create-service-principal.sh b/scripts/create-service-principal.sh index b969d39..2fdf012 100644 --- a/scripts/create-service-principal.sh +++ b/scripts/create-service-principal.sh @@ -41,8 +41,8 @@ if [ "$response" != "y" ]; then exit 1 fi -# Azure sign in -az login +# (Optional) Azure sign in +# az login # Confirm the details for the currently logged-in user az ad signed-in-user show @@ -86,3 +86,18 @@ az ad app federated-credential create \ echo "AZURE_CLIENT_ID: $appId" echo "AZURE_SUBSCRIPTION_ID: $subscriptionId" echo "AZURE_TENANT_ID: $tenantId" + +# Add permissions to the service principal for Microsoft Graph API +# Domain.Read.All, Group.ReadWrite.All, GroupMember.ReadWrite.All, User.ReadWrite.All, Application.ReadWrite.All +MICROSOFT_GRAPH_API_ID="00000003-0000-0000-c000-000000000000" +PERMISSIONS="dbb9058a-0e50-45d7-ae91-66909b5d4664 62a82d76-70ea-41e2-9197-370581804d09 dbaae8cf-10b5-4b86-a4a1-f871c94c6695 741f803b-c850-494e-b5df-cde7c675a1ca 1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9" + +for permission in $PERMISSIONS; do + az ad app permission add \ + --id $appId \ + --api $MICROSOFT_GRAPH_API_ID \ + --api-permissions $permission=Role +done + +# grant admin consent +az ad app permission admin-consent --id $appId