I'm using Azure Data Factory to populate tables in an Azure SQL Database. I want to avoid using SQL Server authentication/Basic authentication. What is the best alternative?
Using the Managed Service Identie of ADF |
Solution
Recently we showed how to give ADF access to a Data Lake via its Managed Service Identity. You can also use that to give ADF access within your database. This will save you the hassle of using accounts and passwords within ADF (or Azure Key Vault).
1) Enable Azure Active Directory authentication
First make sure you are using Azure AD authentication for your Azure SQL Server by adding an Azure Active Directory admin within your SQL Server. Without an AAD admin you cannot add AAD users (or Data Factories) to your database.
Go to your Azure SQL Server (not the database) and under Azure Active Directory in the left menu you can check and change this option. To try it out you just could add your own AAD account as AAD admin.
Enable Azure Active Directory authentication |
2) Create user in SQL DB
Now use your favourite query tool and login to your database with an AAD account that has the db_owner role. Execute the following create-user-command on your database. The user is the name of your Azure Data Factory.
-- Add your Azure Data Factory as external to SQL DB CREATE USER [YourDataFactoryName] FROM EXTERNAL PROVIDER; -- Check the permissions of your Azure Data Factory SELECT DISTINCT pri.principal_id , pri.name , pri.type_desc , pri.authentication_type_desc , per.state_desc , per.permission_name FROM sys.database_principals AS pri JOIN sys.database_permissions AS per ON per.grantee_principal_id = pri.principal_id WHERE pri.name = 'YourDataFactoryName' -- Remove all permission of your Azure Data Factory DROP USER [YourDataFactoryName]
This command gives your ADF connect permissions on your database. This is enough to test the connection of a Linked Service in ADF, but is not enough to actually do something with the data.
3) Give data permissions
Next step is to give your ADF a database role so that it is able to read or write data depending on your needs. This can be done with the stored procedure sp_addrolemember or via the ALTER ROLE command
-- Two options to add a DB role to your ADF -- Add db_datareader role to your ADF EXEC sp_addrolemember N'db_datareader', N'YourDataFactoryName' -- Add db_datawriter role to your ADF ALTER ROLE [db_datawriter] ADD MEMBER [YourDataFactoryName] -- Check roles of your ADF SELECT DP1.name AS DatabaseRoleName , isnull (DP2.name, 'No members') AS DatabaseUserName FROM sys.database_role_members AS DRM RIGHT OUTER JOIN sys.database_principals AS DP1 ON DRM.role_principal_id = DP1.principal_id LEFT OUTER JOIN sys.database_principals AS DP2 ON DRM.member_principal_id = DP2.principal_id WHERE DP1.type = 'R' AND DP2.name = 'YourDataFactoryName' -- Two options to remove the role from your ADF -- EXEC sp_droprolemember N'db_datareader', N'YourDataFactoryName' -- ALTER ROLE [db_datawriter] DROP MEMBER [YourDataFactoryName]
Give ADF permission to read and/or write data |
4) Create Linked Service via MSI
Now create a new Linked Service in ADF and use Managed Identity as the Authenication type. When you do this you don't have to fill in a password. Hit the Test connection button to see if it works.
If it's failing check the firewall/VNet/Subnet settings or check whether you executed the above queries on the correct database.
Conslusion
In this blogpost you learned how easy it is to give ADF persmissions within your database without using accounts and passwords. Note that those permissions are totally different than when you want to scale your database. The same method with the Managed Service Identity can be used to give ADF access to your Azure Storage Account or Azure Key Vault.