currently, we are developing an Azure app service application, which has a system managed identity assigned during setup of the app service. We use the managed identitiy with RBAC to access other Azure resources and that is working fine.
Now I want to get some information from the underlying managed identity to perform some checks. Especially I want to read the application id, which is assigned to this managed identity. I want to do that in C#. How can I access this information?
Any help appreciated. Thanks in advance.
Regards,
Stati
var credential = new DefaultAzureCredential();
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
var token = await credential.GetTokenAsync(new Azure.Core.TokenRequestContext(scopes));
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(token.Token) as JwtSecurityToken;
var appid = jsonToken.Claims.First(c => c.Type == "appid").Value;
Console.WriteLine(appid);
Related
I want to use the communications API in Microsoft Graph using a simple C# desktop app.
For now, let's say I want to use the GET /communications/calls/{id} request that can only be used via Application Permissions.
From my understanding, only bots can use the communications API.
So I've created a bot in Azure and deployed this code:
https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/24.bot-authentication-msgraph
The bot works and I get the user mail etc. but:
The bot uses delegated credentials that are not supported for the Get Call request.
I want to access the API via a C# desktop app using the bot credentials and not using the bot itself(I don't know if this is even possible but logic dictates that it should)
When I try a simple API request using the bot's app credintials (like I would use any other Azure app) I get this response:
{"error":{"code":"UnknownError","message":"","innerError":{"date":"2022-03-31T09:29:44","request-id":"7906abfd-5ba4-439f-939c-42361c2ab255","client-request-id":"7906abfd-5ba4-439f-939c-42361c2ab255"}}}
which is not much help.
I've tried different ways like getting the JWT token for the bot and then using it to get an On-behalf-of provider as shown here:https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=CS and I get this exception:
MsalUiRequiredException: AADSTS50058: A silent sign-in request was sent but no user is signed in.
The code:
var scopes = new[] { "User.Read" };
var tenantId = "common";
var clientId = "appId";
var clientSecret = "appSecrete";
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var oboToken = "JWT token I get form the bot with scope:appId/.default";
var cca = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
var authProvider = new DelegateAuthenticationProvider(async (request) =>
{
var assertion = new UserAssertion(oboToken);
var result = await cca.AcquireTokenOnBehalfOf(scopes, assertion).ExecuteAsync();
request.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken);
});
var graphClient = new GraphServiceClient(authProvider);
string callId = "callId";
var call = graphClient.Communications.Calls[$"{callId}"].Request().GetAsync();
call.Wait(); //-->here exception
var res = call.Result;
So firstly I want to know is it possible to use the communications API from a desktop app using the bot credentials?
If so then I would really appreciate a good explanation of a step-by-step on how to get the Get Call request to work,
specifically how to set up the bot, how to get the correct Access Token for the Graph API.
If not, I would appreciate a code example of using the Get Call API request from inside the bot.
Is it possible to get programmatically the number of app service restarts either as a metric or an alert. Specifically the programmatic equivalent of going to an Azure App service -> Diagnose and solve problems -> Web App restarted and get the dates and times of the restarts.
According to this: Is it possible to see the restart history of an Azure App Service? the activity log also contains the data.
Ideally I want to access this from the Microsoft.Azure.Management.Fluent interface i.e. in C# code.
Yes, you can. Just use the code below to check the activity log, the list in the code is what you want.
Follow the steps below.
1.Register an application with Azure AD and create a service principal.
2.Get values for signing in and create a new application secret.
3.Navigate to the web app -> Access control (IAM) -> Add -> add service principal of the AD App as an RBAC role e.g. Contributor, details follow this.
4.Then use the code below.
using Microsoft.Azure.Management.Monitor.Fluent.Models;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using System;
using System.Collections.Generic;
namespace ConsoleApp14
{
class Program
{
static void Main(string[] args)
{
var clientId = "xxxxx";
var clientSecret = "xxxxx";
var tenantId = "xxxxx";
var subscriptionId = "xxxxx";
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(clientId,
clientSecret,
tenantId,
AzureEnvironment.AzureGlobalCloud);
var azure = Microsoft.Azure.Management.Fluent.Azure
.Configure()
.Authenticate(credentials)
.WithSubscription(subscriptionId);
var logs = azure.ActivityLogs.DefineQuery()
.StartingFrom(DateTime.Now.AddDays(-7))
.EndsBefore(DateTime.Now)
.WithAllPropertiesInResponse()
.FilterByResource("/subscriptions/xxxxx/resourceGroups/xxxxx/providers/Microsoft.Web/sites/joyweba")
.Execute();
List<IEventData> list = new List<IEventData>();
foreach (var log in logs) {
if ((log.OperationName.LocalizedValue == "Restart Web App") & (log.Status.LocalizedValue == "Succeeded")) {
list.Add(log);
}
}
}
}
}
I've registered my app in azure AD and created a client secret and then created a vault and added a secret for the dbconnectionstring below. It works ok but I need the "client-id" and "client-secret" since the identity is managed as service principal. Is there a way to get thos values through an API so that my app doesn't have to save those in the config? It's kind of defeating the purpose since thos whole exercise was to avoid having to save connection strings in the web.config/appsettings.json; as now I can save those in the vault but I would need to save the clientid/secret in the config.
var kvClient = new KeyVaultClient(async (authority, resource, scope) =>
{
var context = new AuthenticationContext(authority);
var credential = new ClientCredential("client-id", "client-secret");
AuthenticationResult result = await context.AcquireTokenAsync(resource, credential);
return result.AccessToken;
});
try
{
var connStrENTT = kvClient.GetSecretAsync("https://myvault.vault.azure.net/", "DBConfigConnection").Result.Value;
}
Why do you need to acquire token via your code if you are using managed identity? Managed identity is supposed to hide this for you.
Please use the guidance provided in a sample like this to take the correct steps.
I want to get a list of users who have the right to use the application.
It is not possible to enter Secret keys in the Native App. I try to use the same accessToken as I log in. Authentication works fine. ObjectId is the same as my native app ObjectId.
result = await authContext.AcquireTokenAsync(graphResourceId, _ADClientId, redirectUri, new PlatformParameters(PromptBehavior.Never));
string accessToken = result.AccessToken;
ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(serviceRoot, async () => await Task.FromResult(accessToken));
var groupFetcher = (IGroupFetcher)activeDirectoryClient.Groups.ExecuteAsync().Result.CurrentPage.First(g => g.ObjectId == "5deedc8c-2ba6-45d8-a4f2-xxxxxxx");
Error: Authorization_RequestDenied
What went wrong?
Within your Azure Active Directory, go to your Application registration and add a delegation permission for the Windows Active Directory API. Im not sure which is the least permission you can select (maybe Sign-in and read user profile may work) but Read directory data will give you the necessary permissions:
I have install nuget Microsoft.Azure.Management.ResourceManager and have following code to get all existing resources based on Resource Group Name
var resouceManagementClient = new ResourceManagementClient(credentials) { SubscriptionId = "mySubscriptionId" };
var listResources =
resouceManagementClient.ResourceGroups.ListResources("Demo-ResourceGroup");
I'm not sure from where I can get credentials parameter value.
I do not have Azure Active Directory access , I think its must , can
we bypass azure AD?.
In my azure portal I have create a Resource Group - Demo-ResourceGroup
and have many resources created.
I want only list of all existing resources using c# code.
One way is by grabbing an access token from Azure AD and passing it in to a TokenCredentials class.
var authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantId));
var credential = new ClientCredential(applicationId, password);
AuthenticationResult token = authContext.AcquireTokenAsync("https://management.core.windows.net/", credential).Result;
var credentials = new TokenCredentials(token.AccessToken);
The set of credentials you use to request the acces token (in this case clientId/secret) will determine whether the application has the appropriate rights to enumerate the resources. This is a good MS docs page on how to register your application with AAD. In the example above, applicationId and password come from the application registration in AAD
Microsoft has a page describing other ways you can get tokens from AAD.