# Service Principal For Azure

In an earlier [article](https://www.azureguru.net/managed-identities-in-microsoft-azure) on Managed Identity in Azure, I demonstrated how managed identity can significantly enhance the security and efficiency of your cloud applications. By using managed identities one can eliminate the need to manage credentials manually reducing the risk of credentials being exposed or misused. Managed identities allow Azure services to authenticate without needing to store credentials in the code or configuration files. This approach simplifies authentication and increases overall security of the Azure systems.

### Why use Service Principal ?

There are some nuances that one should be aware of when it comes to service principal. Passwords or secrets associated with Service Principals have expiration periods and require regular rotation. This is especially handy when you would want to provide expiry based authentication for the applications. For example, you would want to provide access to certain systems or applications only for a limited period of time without worrying about manually tracking the expiration or revoking credentials, and without needing to embed credentials within the applications themselves. Though the management of Service Principal credentials still poses challenges the biggest advantage being that the credentials can be centrally managed and has a certain expiry.

### What is Service Principal ?

A Service Principal in Azure can be defined as an identity created for applications and services that can be used to securely authenticate and access Azure resources. It acts as an Azure AD entity with assigned permissions, allowing services to interact with resources like databases or storage. Service Principals typically use client ID and secret credentials, which need to be securely managed and rotated regularly.

### The Setup

To get started we need to register the application at [**entra.microsoft.com**](http://entra.microsoft.com)

[Once logged in, na](http://entra.microsoft.com/)vigate to **Applications &gt;&gt;App registrations &gt;&gt; New registration**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724690897503/35730069-9cfa-438d-b3b5-d15cd01735f7.png?auto=compress,format&format=webp&auto=compress,format&format=webp&auto=compress,format&format=webp align="left")

I registered the application under the name `SP_ADF_POC`. We would required `ClientId` and `TenantId` values to reference in the code from the registered app.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729631203027/2d4ff3fb-af19-4170-9545-c6a98d3e4105.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729631698037/eabdfb81-968f-4b3f-ba9b-97d5f2a0534e.png align="center")

Clicking the `New client secret` allows you to set the expiry for the Service Principal credentials.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729631434627/bd3cb5c7-ad3c-4ab1-8222-50ad0bd481af.png align="left")

Now that the feature is enabled and all set, lets create a ADF package that imports data from a text file on a Blob container into a Azure SQL database. We will create a empty Azure Data Factory and then add components to import data from a text file on a Azure container into a Azure SQL Database.

We can do it through Azure portal or PowerShell.

To get started with PowerShell, we have to install the following PS modules.

```powershell
Install-Module -Name Az -AllowClobber -Force
Install-Module -Name Az.Sql -AllowClobber -Force
Install-Module -Name Az.DataFactory -AllowClobber  -Force
Install-Module -Name Az.Resources -AllowClobber -Force
Install-Module -Name Az.ManagedServiceIdentity -AllowClobber -Force
Install-Module -Name Az.Storage -AllowClobber -Force
```

Incase if you need to upgrade your PowerShell environment you can do it through the following command

```powershell
winget install --id Microsoft.PowerShell --source winget
```

### **Code**

Connect to Azure PowerShell. You can use PowerShell ISE.

```powershell
Connect-AzAccount
```

***In PowerShell***

```powershell
$resourceGroupName = "Your Resource Group" 
$sqlServerName="adf-sqlserverdb"
$aadAdmin="User to be assigned as Azure SQL server admin"
Set-AzSqlServerActiveDirectoryAdministrator `
  -ResourceGroupName $resourceGroupName `
  -ServerName $sqlServerName `
  -DisplayName $aadAdmin `
  -ObjectId (Get-AzADUser -UserPrincipalName $aadAdmin).Id
```

***In Azure Portal***

Set the admin for Azure SQL instance. The Sql instance in this case is `adf-sqlserverdb`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1728929056037/4f5208c8-be07-4d81-b7df-2ff2f349e909.jpeg?auto=compress,format&format=webp align="left")

You also might want to set up Network access to the Azure Sql Server instance.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1728929439397/493960b3-f352-417a-9813-f70bd249edae.png?auto=compress,format&format=webp align="left")

Lets connect to the Azure SQL Instance `adf-sqlserverdb` through SSMS and create a database named `SP_ADF_POC` and create a table that maps the source data schema. I named the table as `tbl` and has 2 columns `date` and `values`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1728942557615/8391bc55-4944-4b53-a063-926428a269a4.png?auto=compress,format&format=webp align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729636384843/d7933128-a20d-418e-914c-d3e34ddfab0f.png align="left")

The SSMS connection to the Azure Sql works ok as I have logged in through the Entra authentication which was assigned as a admin to the instance.

Next we create a ADF pipeline that uses Service Principal.

***In PowerShell***

```powershell
$TenantId = "TenantId of the registeted app in Entra" 
$ClientId = "ClientId of the registeted app in Entra"
$ClientSecret = "ClientSecret of the registeted app in Entra"
$resourceGroupName = "Your Resource Group"
$DataFactoryName="ADF-User-Service-Principal"
$Location = "Central India"
$SecureClientSecret = ConvertTo-SecureString $ClientSecret -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ClientId, $SecureClientSecret
Connect-AzAccount -ServicePrincipal -Tenant $TenantId -Credential $Credential
Set-AzDataFactoryV2 -ResourceGroupName $ResourceGroupName -Name $DataFactoryName -Location $Location
```

The above code should create a ADF named `ADF-User-Service-Principal`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729637984759/f77dec3e-0269-40ea-ada8-1a6f77265a99.png align="left")

You can alternatively create the ADF through Azure Portal. Point to be noted, is that we wont have to set any managed identities to this resource, instead we have to grant contributor access to the service principal through `IAM » Add role assignment`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729638258147/605d80e6-621b-4ed5-a8ff-5bdc1ed5df2b.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729638696337/39de3f26-a812-4da1-a5f0-e0dfb05c6330.png align="center")

Once done the service principal should be visible under the Role assignments tab

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729638871958/10414224-ff81-4fe1-abf8-0949eb03572c.png align="center")

Now create a linked service to a blob storage(`location: temporaryontainer/destination`) where the text file resides using the service principal details.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729639416706/20c3344c-3416-4882-a9a4-3dd02184cc36.png align="left")

As expected the connection failed. This is because the service principal has no access to the blob container. To fix this issue, grant `Storage Blob Container Contributor` access to the service principal.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729639813088/b755d51e-6638-40ff-ad66-1c9c9c27dfbe.png align="center")

Once done, retest the linked service connection and this time it should succeed

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729640214105/d5ccfe83-3f04-43ef-9245-856313f80060.png align="left")

Next create a linked service to connect to the Azure SQL database.The connection to the SQL database failed.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729640493946/e1f17608-5da4-450f-b3f2-e4f9859f2a9f.png align="left")

This is because the service principal `SP_ADF_POC` is not a user in the database `SP_ADF_POC`. So we would have to add this service principal as a user to the database.

```sql
CREATE USER [SP_ADF_POC] FROm EXTERNAL PROVIDER;
GO
ALTER ROLE db_owner ADD MEMBER[SP_ADF_POC]
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729640689327/b7b1e122-993c-4067-a3b0-11ef31617073.png align="left")

I hope the names that I used do not cause confusions, as I have used the name `SP_ADF_POC` both for the service principal and SQL Database.

Retest the connection and this time the database connection should succeed.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729640783959/20831390-dab6-4e9e-bd84-edeb02ecc7ea.png align="left")

Now that all the settings are in place, lets now create a simple data pipeline that imports data from a text file to the SQL database in table `tbl`. Set the Source and Sink of the pipeline to the linked services created earlier.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1728942905840/0acad802-6fd6-4024-9a14-00ecc99affb9.png?auto=compress,format&format=webp align="left")

Execute the package and it should succeed.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729643326473/7a083af5-34c6-4b26-8799-ee8410ca440e.png align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729645847033/e327ac39-dd93-426f-a64e-76c0ee13b614.png align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729645078553/6eccc87f-5b66-41ec-a2c8-06571e8a5886.gif align="center")

### Conclusion

In conclusion implementing service principals in Azure streamlines the authentication process for certain use cases where you would want to maintain credentials across Azure services and applications without the overhead of needing to store credentials in the code or configuration files.

Thanks for reading !!!
