I have followed this tutorial to secure Azure SQL Database connection from App Service using a managed identity.
Everything is working as expected in Azure, but when I am trying to debug the code locally I am getting below error message while opening the connection.
Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.
I found few references where they have mentioned we can use 'Azure Service Authentication' extension to debug locally.
I have logged into my Azure account in 'Azure Service Authentication' extension. But, still I am getting the error.
public IActionResult GetData()
{
var result = "connection opened.";
var test = config.GetSection("ConnectionStrings")["MyDbConnection"];
SqlConnection sql = new SqlConnection();
sql.ConnectionString = test;
sql.AccessToken = (new AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result; //No issues while fetching the token.
try
{
//Getting exception here when running locally...
//Same code is working in Azure Webapp.
sql.Open();
}
catch (Exception ex)
{
result = $"Error : {ex.Message}";
}
finally
{
if ( sql != null && sql.State == System.Data.ConnectionState.Open )
{
sql.Close();
}
}
return Ok(result);
}
Other Details:
Visual Studio 2019 Community - Version 16.1.0 Preview 3.0
.NET Core 2.2
UPDATE 1:
This post talk about connectionString parameter for AzureServiceTokenProvider class. I tried providing RunAs=Developer; DeveloperTool=VisualStudio value for connectionString but still facing same issue.
Got below answer on Microsoft forum
Hello Hemant
I can see from the screenshot that you are logged in to Visual Studio with your Live ID.
Is the database created in a tenant associated with a work account?
Which user is set as AAD Admin on the Azure SQL Server?
The user account with which you are logged in to VS should be added as a user on the database for the authentication to work.
Alternatively, in the same article the you referenced, there is a section that talks about creating an AAD group and granting appropriate permissions.
You can add your user to the AAD group as well.
Please let us know if you have further questions.
Proposed as answer by Kalyan Chanumolu-MSFTMicrosoft employee, Moderator Wednesday, May 22, 2019 3:55 AM
Marked as answer by Hemant.Shelar Wednesday, May 22, 2019 4:22 AM
Wednesday, May 22, 2019 3:55 AM
Note: I was able to get it done by creating AAD group and granting appropriate permissions.
UPDATE 1:
I have followed below steps to get it work. Let me know if there exists any other possible solution
Created a AAD group e.g. 'hemantdotnetcore1'
Add users to this group ( generally these users will be developers
in DEV environment who want to access the database during
development )
Navigate to the SQL server instance and set 'Active Directory
admin'. In this example I have added 'hemantdotnetcore1' as a
active directory admin.
In visual studio navigate to 'Azure Service Authentication' and
log in with any one user who is part of group 'hemantdotnetcore1'
which is my Azure Active Directory Admin'
Now I can use below toke to open connection with the SQL Server.
sql.AccessToken = (new AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result;
Related
I am trying to configure connecting to azure sql using managed identity. However before, I need to connect to sql azure from visual studio using AD identity.
I have followed steps here.
https://learn.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-sql-database?tabs=windowsclient%2Cef%2Cdotnet#3-modify-your-project
I have this code in console app.
SqlConnectionStringBuilder builder = new
Microsoft.Data.SqlClient.SqlConnectionStringBuilder();
builder.DataSource = "sqlserveraddress";
builder.InitialCatalog = "dbaddress";
string connstring = builder.ConnectionString;
await using var conn = new Microsoft.Data.SqlClient.SqlConnection(connstring)
{
AccessToken = await GetAzureSqlAccessToken()
} ;
await conn.OpenAsync();
As required, I have added my visual studio App service authentication identity user in sql azure db.
CREATE USER "user#domain.com" FROM EXTERNAL
PROVIDER;
ALTER ROLE db_datareader ADD MEMBER
"user#domain.com";
ALTER ROLE db_datawriter ADD MEMBER
"user#domain.com";
ALTER ROLE db_ddladmin ADD MEMBER
"user#domain.com";
GO
Now if i try running my console application, I get following error.
If i try to decode the access token it shows the user I have added to sql azure. user#domain.com.
What Am I Missing here??
You need to set the created Managed Identity as admin in SQL Server.
Follow this: Azure SQL Server -> Settings -> Azure Active Directory
Now click on Set Admin option and search for the Managed Identity to which you want to give access.
Click on Save.
I am trying to get the access token for the Azure function app. I have enabled managed identity for the function app(system assigned). but while fetching the token using the nuget Azure.Identity.
var tokenCredential = new DefaultAzureCredential();
var accessToken = await tokenCredential.GetTokenAsync(
new TokenRequestContext(scopes: new string[] { "https://xxx.azure-api.net/" + "/.default" }) { }
);
I am getting the error.
The resource principal named 'xxx.azure-api.net' was not found in
the tenant 123
but when run az cli to check the subscription details, the subscription indeed part of the tenant 123 only.
Here is what I have finally done.
I have registered an App in AD. and Exposed the API of that App.
I have assigned System Assigned Managed Identity to the Function.
In the local I am not able to request token because Azure CLI is not given consent.
After deploying the application in Function my Function app can request a token using its identity.
You need to register the application in azure ad and enable the access token. Once that is done the you need to provide RBAC access to your xxx.azurewebsites.net
Follow this article for the step by step documentation Microsoft Document Reference
Unfortunately, the error message is not really helpful. But adding a scope to the app registration solved the problem for me:
In Azure Portal navigate to App Registrations
Find your app, in the left side menu select Manage => Expose an API
Add a scope. I named mine api_access as this was where this error occurred.
In my case I then got an API URI (like api://client-id/scope_name) which I used in my Angular app. Error message was gone.
Also, make sure that in the Enterprise Application you have created, under Manage => Properties, "Assignment required" and "Visible to users" is turned on.
I'm attempting to access Azure Service Bus using a managed identity from my code. At the moment I'm just trying this locally.
When I debug my code I get the following error
System.UnauthorizedAccessException: Put token failed. status-code: 401, status-description: InvalidIssuer: Token issuer is invalid
Here is my service bus instance
Here is my user with Azure Service Bus Data Owner permissions
And here is my code
_client = new ServiceBusClient("oconnorevents.servicebus.windows.net", new DefaultAzureCredential());
I am logged into Visual Studio as the same user added to the service bus. I also tried logging in via the CLI but it didn't help.
Where am I going wrong here?
I've looked at this similar recent question here but the solutions proposed didn't work for me.
Since I have access to several different tenants, Visual Studio sometimes gets confused. Another way you can handle this is to continue to use the DefaultAzureCredential, but to give Visual Studio a hint about which tenant to use.
First left click the your project and examine the properties and then:
Left-click "Debug"
Left-click the "Add" button to add an environment variable
For name use "AZURE_TENANT_ID" and for value use your tenant id. Yes, that is a bogus tenant id in the picture :-)
Reference
https://learn.microsoft.com/en-us/dotnet/api/azure.identity.environmentcredential?view=azure-dotnet
https://damienbod.com/2020/10/09/using-key-vault-certificates-with-microsoft-identity-web-and-asp-net-core-applications/
If you use DefaultAzureCredential to auth, it will try several credential types to auth as mentioned here, one of them is VisualStudioCredential, but it will auth to the home AAD tenant of the user logged in VS, in your case, I suppose the service bus is in a subscription which is not under the home tenant of the user.
I can also reproduce your issue on my side.
To solve the issue, just use VisualStudioCredential directly, then simply specify the TenantId via VisualStudioCredentialOptions, then it will work fine.
Sample:
To find the TenantId, just navigate to the Azure Active Directory which the subscription of your service bus located.
TokenCredential tokenCredential = new VisualStudioCredential(new VisualStudioCredentialOptions {TenantId = "xxxxxxx" });
ServiceBusClient client = new ServiceBusClient("xxx.servicebus.windows.net", tokenCredential);
Specify the exact tenant id by adding the following key to local.settings.json.
"AZURE_TENANT_ID": "your tenant id"
I tried to create an azure function that receives messages from a service bus queue using a managed identity trigger and it worked for me.
late to the party but I got it working on my local Visual Studio with this code
var tokenCredential = new VisualStudioCredential(new VisualStudioCredentialOptions { TenantId = "xxx-xxx" });
ServiceBusClient client = new ServiceBusClient("my-name-space.servicebus.windows.net", tokenCredential);
sender = client.CreateSender('my-topic');
var msgBody = new Person{ Name = 'joe'};
await sender.SendMessageAsync(new ServiceBusMessage(JsonConvert.SerializeObject(msgBody)));
Also, remember to sign in to Azure in your Visual Studio,
and assign your account to the role "Azure Service bus Data Sender" , see below:
I am running the following functionality as a part of Main method of my .net core web application
private static void LinkKeyVault(IConfigurationBuilder config, string keyVaultEndpoint)
{
if (!string.IsNullOrEmpty(keyVaultEndpoint))
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
config.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
}
}
When I am running this code on my local dev machine I am getting the following error "Operation returned an invalid status code 'Forbidden'". When this code runs in Azure under app service user assigned managed identity everything works just fine. On my local environment I am logged in with my Azure AD user which was granted access permissions using key vault access policy, the permissions are the same as for user assigned managed identity.
dfrds-dev-web-identity is the user assigned managed identity, DFRDDevelopers is a group that my Azure AD account is a part of.
It should work, please make sure the group in which the user account located is a Security group, not a Microsoft 365 group, just the Security group is supported in this feature.
Reference - https://learn.microsoft.com/en-us/azure/key-vault/general/secure-your-key-vault#data-plane-and-access-policies
To grant data plane access to several users, create an Azure AD security group and add users to that group.
Also, if you want to use Visual Studio to auth, make sure you logged in with the correct account, and try to use RunAs=Developer; DeveloperTool=VisualStudio in the code to make sure it uses the Visual Studio to auth.
var azureServiceTokenProvider = new AzureServiceTokenProvider(RunAs=Developer; DeveloperTool=VisualStudio);
Using VS2019, I have specified a temporary "developer account", using Tools/Options/Azure Service Authentication/Account Selection, for my app to "authenticate and access Azure resources with when debugging from Visual Studio". The developer account has access to an Azure SQL database. When I debug, my app gets a token as follows:
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder["Data Source"] = serverName;
builder["Initial Catalog"] = dbName;
builder["Persist Security Info"] = "False";
builder["MultipleActiveResultSets"] = "False";
builder["Encrypt"] = "True";
builder["TrustServerCertificate"] = "False";
builder["Connect Timeout"] = 15;
var cancellationToken = new CancellationToken();
var conn = new SqlConnection(builder.ConnectionString);
conn.AccessToken = new AzureServiceTokenProvider().GetAccessTokenAsync("https://database.windows.net/").GetAwaiter().GetResult();
return conn.AccessToken;
However, when I examine the token returned it is NOT the token for the developer account identity I specified, it is for my normal identity I use to run Visual Studio. A co-worker has been able to do this in VS2019 with a developer account that's in the same Azure AD groups as my developer account. But for some local environment reason this is not working for me. Note that in SQL Server Management Studio I can access the SQL Azure database using my developer account with no problem at all.
Has anyone else had this debugging identity problem and been able to solve it? Thanks in advance for any light you can shed on this.
Sounds like you need to add the developer account to your Azure Service Authentication
On the drop down add the Dev account you are trying to use and make sure you make it your default account for Azure.