I need to create app registration and then add it as Identity provider to app service programmatically (by bicep).
It's possible to create app registration using Deployment Scripts.
But how I can add it to app service?
For creating app service we use Microsoft.Web sites 2020-12-01.
But I don't see any property for Identity provider.
We have property identity, but it's for ManagedServiceIdentity.
Maybe Microsoft.Web sites/config 'authsettings'?
But:
The sites/config resource type can be deployed to: Resource groups.
So, question is: is it possible to add Identity provider by bicep or I should do it manually?
You can use authsettingsV2. Full documentation can be found here.
param webappname string
resource webapp 'Microsoft.Web/sites#2022-03-01' existing = {
name:webappname
}
resource authsettings 'Microsoft.Web/sites/config#2022-03-01' = {
parent: webapp
name: 'authsettingsV2'
properties:{
...
}
}
You can also refer to a similar post: ARM template for Azure Function with V2 Authentication.
Related
I'm trying to deploy Azure resources using Bicep templates and Azure Pipelines.
So far I managed to deploy a web app, but I'm struggling to register it in Azure AD.
There is a job in my pipeline which should create an app in Azure AD:
This job fails with the following error:
ERROR: Insufficient privileges to complete the operation.
I also tried to use az rest command like so
and got similar error:
ERROR: Forbidden({"error":{"code":"Authorization_RequestDenied","message":"Insufficient privileges to complete the operation.","innerError":{"date":"2022-03-01T07:18:30","request-id":"903fcd87-ad15-4766-8f31-132185e2c97d","client-request-id":"903fcd87-ad15-4766-8f31-132185e2c97d"}}})
It's clear that the service connection used by the pipeline doesn't have some necessary permissions, but I cannot figure out which one.
The service connection has the Owner role. Here are API permissions of the service connection:
There is an answer to similar question suggesting that I need the Application.ReadWrite.All in Azure AD Graph, but Azure AD is deprecated:
Any help would be appreciated!
You should use the Microsoft Graph instead and select the appropriate permissions there.
Another option would be to let the bicep template of the web app add a system managed identity for you by using the SystemAssigned in the identity property:
resource appService 'Microsoft.Web/sites#2020-06-01' = {
name: webAppName
location: location
properties: {
serverFarmId: appServicePlan.id
siteConfig:{
alwaysOn: true
}
httpsOnly: true
clientAffinityEnabled: false
}
identity: {
type: 'SystemAssigned'
}
}
I am trying to create a Client_secret for My service principal using the below code :
data "azuread_service_principal" "existing_SP" {
display_name = "TestAppRegistration"
}
resource "azuread_service_principal_password" "Client_Secret" {
service_principal_id = data.azuread_service_principal.existing_SP.object_id
}
Doing a terraform-apply it get successfully created but I don't see it in the Secrets and certificates section of the app registration:
But when I check the tfstate , it shows the value there created for the service principal but the object Id is same as the enterprise application present for the same app registration:
So, My question:
How can I create a client secret using terraform, is there something I am doing wrong ?
If I am doing correct then where is the secret generated can be found in portal?
How can I create a client secret using terraform, is there something I
am doing wrong ?
Yes , You are doing everything correctly.
But to clear the confusion here , as you may already know there are 2 types of azure ad application i.e. app registrations and enterprise application. In terraform or powershell or cli the App Registration is know as Azure AD application and the Enterprise Application for the same app registration is know as Service Principal. So , if you have created from Portal by going to app registration blade , then bydefault a service principal is created for it , but its not the same if you create a app registration from Powershell or Terraform.
And By default you will be not be able to see the secret or certificate created for service principal from portal but you will be defintely able to use it with the client-id for authentication purpose .
For example :
I tested this on my environment using your code and I took the value of password present in tfstate file and used it to do az login:
Note: Its safe to use terraform for creating a service principal password as it will be stored in the tfstate file so, you won't face difficulty in searching for it .
If I am doing correct then where is the secret generated can be found
in portal?
But if you are trying to look for the secret from portal , then I will suggest you to use azuread_application:
data "azuread_application" "example" {
display_name = "postman"
}
resource "azuread_application_password" "example" {
display_name = "terraformgenerated"
application_object_id = data.azuread_application.example.object_id
}
I was wondering if there was a way to get an App Client Id by using either it's App Name or App ID URI in ARM template (maybe by using a reference function)
No, it is not possible to get the Client id via the App name or App ID URI.
The AD App is a resource in Azure AD, it is not a resource in the subscription, ARM template is for the resources in Azure subscription.
Reference - https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/overview
Azure Resource Manager is the deployment and management service for Azure. It provides a consistent management layer that enables you to create, update, and delete resources in your Azure subscription.
I have a project that is running on Azure DevOps that requires creating a KeyVault and giving a series of managed AppService identities access to secrets in that vault.
Because of Terraform not being able to give its own service connection access to the key vault(this is a bug of some kind), I am forced to create ResourceGroup and Keyvault with SP access before Terraforming.
When running terraform import on resourcegroup and Keyvault through a PowerShell task:
terraform init
$state = terraform state list
if ($state -like '*azurerm_resource_group.instancerg*' -and '*azurerm_key_vault.instancekeyvault*') {
Write-Host "Resources have already been imported!"
}
else {
terraform import azurerm_resource_group.instancerg /subscriptions/$(subscriptionid)/resourceGroups/rgname
terraform import azurerm_key_vault.instancekeyvault /subscriptions/$(subscriptionid)/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/keyvaultname
}
Failure happens on terraform import commands:
'Authenticate using a Service Principal' To authenticate to Azure
using a Service Principal, you can use the separate auth method -
instructions for which can be found here:'
My main.tf contains:
provider "azurerm" {
version = "=2.7.0"
subscription_id = var.subscriptionid
client_id = var.devopsserviceconnectionaid
client_secret = var.devopsserviceconnectionpw
tenant_id = var.tennantid
features {}
}
The variables are all linked to the proper credentials.
From what I understand Terraform should pick up on what authentication method that is being used based on the credentials that are in the block above or specific env variables (that are also present...) but somehow Terraform still thinks I'm trying to auth through Azure Cli and not Service principal.
You can use manage identities in keyvault in terraform as shown below.
object_id = azurerm_app_service.app.identity.0.principal_id
Web app is as below creating managed identity
KV as below
The order should be create web app with managed identity, then the KV then the KV access policy.
For authenticate with Azure pipelines service connection below works fine but you need to pass the arguments via the pipeline.
for further information check this blog here
Full PowerShell based implementation calling terraform with Azure DevOps pipelines is explained here. This implementation prevents any azure resources as prerequisite before terraforming. Only prerequisite is creating the SPN to enable authentication and authorization.
I am looking at this example from the terraform docs for creating an azure group:
resource "azurerm_resource_group" "test" {
name = "testResourceGroup1"
location = "West US"
tags = {
environment = "Production"
}
}
It does not specify the subscription anywhere.
How can I specify the subscription?
For your issue, you know the Terraform deploy the Azure resources through the Azure CLI. And there are four ways to authenticate.
Authenticating to Azure using the Azure CLI
Authenticating to Azure using Managed Service Identity
Authenticating to Azure using a Service Principal and a Client Certificate
Authenticating to Azure using a Service Principal and a Client Secret
If you do not set the tenant Id and subscription Id in the Terraform code, then you must use the first method in default. And you authenticate via the Azure CLI with the account that you log in the Azure CLI. So which subscription you set in the CLI then you use it for your Terraform.
But as the Terraform recommend:
We recommend using either a Service Principal or Managed Service
Identity when running Terraform non-interactively (such as when
running Terraform in a CI server) - and authenticating using the Azure
CLI when running Terraform locally.
So that you could grant the more appropriate permission for the service principal as you want.
Subscription is set when you configure Terraform to log in to Azure. The recommended way is to use an Azure AD service principal and environment variables.
To configure Terraform to use your Azure AD service principal, set the following environment variables, which are then used by the Azure Terraform modules. You can also set the environment if working with an Azure cloud other than Azure public.
ARM_SUBSCRIPTION_ID
ARM_CLIENT_ID
ARM_CLIENT_SECRET
ARM_TENANT_ID
ARM_ENVIRONMENT
Reference