I must be missing something silly. I'm trying to authenticate my server backup app to have access to my Azure account so I can do things like programmatically create storage accounts, etc. If I understand right, you have to create a service principal. I think I got that taken care of, now I just need to add the code:
AzureCredentials credentials = AzureCredentials.FromServicePrincipal(client, key, tenant, AzureEnvironment.AZURE);
Azure azure = Azure.authenticate(credentials).withSubscription(subscriptionId);
Problem is references for "AzureCredentials" and "Azure", or "IAzure" all can't be found. I've installed the Azure SDK, added references as follows:
using Microsoft.WindowsAzure;
using Microsoft.Azure;
using Microsoft.WindowsAzure.Management;
using Microsoft.WindowsAzure.ActiveDirectory.Authentication;
...nothing! What am I missing?
EDIT: The suggested package in the answer below was correct, except the "Azure" reference still can't be found. I believe it is in "Microsoft.Azure.Management.Fluent", but when I try to add it, I'm getting this:
Failed to add reference. The package 'Microsoft.Azure.Management.AppService.Fluent' tried to add a framework reference to 'System.Xml.XDocument' which was not found in the GAC. This is possibly a bug in the package. Please contact the package owners for assistance. 0
You should use Microsoft.Azure.Management.ResourceManager.Fluent sdk and refer to document , you could try below code to login with ServicePrincipal :
AzureCredentials credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(...)
OR
var credentials = new AzureCredentials(new ServicePrincipalLoginInformation { ClientId = "xxxxxx", ClientSecret = "xxxxx" }, "tenantid", AzureEnvironment.AzureGlobalCloud);
Related
I have set up a test project that follows this microsoft guide: https://learn.microsoft.com/en-us/azure/app-service/scenario-secure-app-access-microsoft-graph-as-app?tabs=azure-powershell
The only difference that I made from that tutorial is the code portion. I changed it to look like this:
TokenCredential tokenCredential = new DefaultAzureCredential();
var scopes = new[] { "https://graph.microsoft.com/.default" };
var graphClient = new GraphServiceClient(tokenCredential, scopes);
var group = graphClient.Groups["<my-group-id>"].Request().GetAsync().Result;
Everything works as expected when I publish the website and access it, but when I run this code locally I receive
Insufficient privileges to complete the operation.
I am signed into VS using the same account that I am using in Azure portal (it's a global admin account). Is there any other configuration setting that I am missing so that I can run this code and test locally?
Usually you need one of the following permissions to query groups i.e delegated and application permissions : GroupMember.Read.All, Group.Read.All, Directory.Read.All, Group.ReadWrite.All, Directory.ReadWrite.All User.Read.All
Run VS as administrator and also give user administrator role.
But visual studio may not work in this case . So please try with
different credential type like client secret/certificate credential
with your app .
In local debugging ,use Shared Token Cache Credential ,as in
your local environment, DefaultAzureCredential uses the shared token
credential from the IDE.
In Visual Studio, you can set the account that you want to use when
debugging using VS : under Options -> Azure Service Authentication.
Please check Azure Managed Service Identity And Local Development by Rahul Nath (rahulpnath.com)
If multiple accounts are configured, try to set the SharedTokenCacheUsername property to that specific account to use.
var azureCredentialOptions = new DefaultAzureCredentialOptions();
azureCredentialOptions.SharedTokenCacheUsername = "<azure ad User Name>";
var credential = new DefaultAzureCredential(azureCredentialOptions);
Reference: DefaultAzureCredential: Unifying How We Get Azure AD Token | Rahul Nath (rahulpnath.com)
I am creating a script using Azure CLI that will automatically generate an App Registration (service principal), and then use that App Registration to create a secret that will be stored in Azure Key Vault.
However, I am getting the following error:
The user, group or application 'appid=04b07795-8ddb-461a-bbee-02f9e1bf7b46;oid=0ec2b0e8-daeb-46a8-b627-0d4f61f87157;numgroups=134;iss=https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/' does not have secrets set permission on key vault 'asakeyabcfelaqpgsfnxcy;location=eastus'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287
Can anyone provide guidance on what this ID is and how to resolve this error? This is not my App Registration Object ID or App ID.
I think there're 2 points you're now concerning, one is you failed to add secret, another is the app id in the error message is not the one you registered.
I think you've followed the document to execute the cli command, so I just want to explain the second point. Pls allow me show you a code sample for a better explanation.
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
public async Task<IActionResult> PrivacyAsync()
{
var kvUri = "https://your_vault_name.vault.azure.net/";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
_ = await client.SetSecretAsync("test0311", "hello");
return View();
}
When we want to add key vault secret to azure, we need to provide a credential so that our operations are authenticated. This is the DefaultAzureCredential() here, and it has several sources to get the authentication like screenshot below.
That means if someone sets the environment variables for authentication, then it will cover the information you entered when executing cli command, this may usually cause the issue that the app is different from what you set. I think you may follow this document to check all your configurations and try again, or you can directly add environment variables with the app you registered on your computer.
By the way, pls don't forget to add access policy in azure portal for the azure ad app you registered.
I am trying to set a secret in azure keyvault using managed identity. There are two problems which I am facing right now. Hope someone can help me with it.
Code:
var client = new SecretClient(new Uri("keyvaulturl"),
new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{ ExcludeManagedIdentityCredential = true }));
await client.SetSecretAsync(new KeyVaultSecret(keyName,
serializer.SerializeObject(someobject)));
Problem 1:
DefaultAzureCrendetialOption is not working for managed identity but when I am setting ExcludeManagedIdentityCredential to true it is able to fallback to the next authentication provider (must be azure cli). I am not sure why this is happening because couple of days before the same code was working and I was able to set and retrieve keyvault secrets using the same code.(ofcourse without using any DefaultAzureCredentialOptions parameters).
Please note this problem only happens in my local env and managed identity works fine when deployed in azure.
Problem 2:
When setting ExcludeManagedIdentityCredential to true for local development, I started seeing another problem where it is giving me error that api-version is missing. I dont understand why and where do I need to specify the api version when using azure .net sdk.
Error:
Service request failed.
Status: 400 (Bad Request)
Content:
{"error":{"code":"BadParameter","message":"api-version must be specified"}}
Problem 1:
Managed Identity cannot be used to authenticate locally-running applications by design. Try to read the Important tip in the document.
Managed Identity cannot be used to authenticate locally-running
applications. Your application must be deployed to an Azure
service that supports Managed Identity.
Problem 2:
Please change the version of Azure Key Vault secret client library with the latest varsion.
dotnet add package Azure.Security.KeyVault.Secrets
I tried DefaultAzureCredential with environment variables in my local.
string keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME");
var kvUri = "https://" + keyVaultName + ".vault.azure.net";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
KeyVaultSecret secret = new KeyVaultSecret("testdefault", "123456");
KeyVaultSecret result = await client.SetSecretAsync(secret);
Console.WriteLine(result.Name);
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 have an Azure app registered on Azure portal which is created in .NET Core 2.0 This app reads some config value from the Application settings section from the portal as shown in below image.
Now at some stage I want to update those config value from code. I have searched for many article but not found how to update Azure Application settings from code. Can any one have an idea or suggestion that How can I update Azure Application settings using .NET Core 2.0 C#?
This can be accomplished using Azure.ApplicationModel.Configuration nuget package.
In particular, the SetConfigurationSetting method seems to do what you are after.
string connectionString = "<connection_string>";
var client = new ConfigurationClient(connectionString);
ConfigurationSetting setting = client.SetConfigurationSetting("some_key","new_value");
Note: This package is in preview
You could use c# to call the REST API Web Apps - Update Application Settings manually.
PUT https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/config/appsettings?api-version=2019-08-01
For more details about how to call Azure REST API in c#, you could refer to this link.
If you want to use c# to do it, you could try with Microsoft.Azure.Management.Fluent package, the below is the sample code, you could have a try.
string tenantId = "*******";
string clientSecret = "********";
string clientId = "********";
string subscriptionId = "*******";
var azureCredentials = new AzureCredentials(new
ServicePrincipalLoginInformation
{
ClientId = clientId,
ClientSecret=clientSecret
}, tenantId, AzureEnvironment.AzureGlobalCloud) ;
var _azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(azureCredentials)
.WithSubscription(subscriptionId);
var appResourceId = "/subscriptions/**********/resourcegroups/*******/providers/Microsoft.Web/sites/***"; //Get From WebApp -> Properties -> Resource ID
var webapp = _azure.WebApps.GetById(appResourceId);
webapp.Update()
.WithAppSetting("test", "testvalue")
.Apply();
The library has been changed to Azure.Data.AppConfiguration.
Azure.ApplicationModel.Configuration is depracated
This is an addendum to George Chen's answer.
To avoid the "Operation returned an invalid status code 'Forbidden' exception after calling _azure.WebApps.GetById(appResourceId), you need to ensure the service principal associated with the Azure Credential has contributor access to the subscription the web app is in. For more details refer to https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal.