I'm trying to configure some automation for a large cloud service that requires many different instances of application insight. Is there a way to extract instrumentation key based on application insight name? Through some management library perhaps?
Yes, there is .net library for that.
First, install the following nuget packages in your project:
Install-Package Microsoft.Azure.Management.ApplicationInsights -IncludePrerelease
Install-Package Microsoft.Azure.Services.AppAuthentication -IncludePrerelease
Then, write a method which return the instrumentation key based on app insights name.
static string GetIKey(string app_insights_name)
{
string IKey = "";
var auth = new AzureServiceTokenProvider();
const string url = "https://management.azure.com/";
string token = auth.GetAccessTokenAsync(url).Result;
var cred = new TokenCredentials(token);
var client = new ApplicationInsightsManagementClient(cred)
{
//replace with your subscription id
SubscriptionId = "your-subscription-id",
};
var list = new List<ApplicationInsightsComponent>();
var all = client.Components.List();
list.AddRange(all);
foreach (var item in list)
{
if (item.Name.ToLower() == app_insights_name.ToLower())
{
return item.InstrumentationKey;
}
}
//if no app insights name matches, return ""
return "";
}
Test result:
Related
I am trying to create multiple VMs to multiple Subscriptions programmatically. So I need to list all subscriptions that I can access. But I cannot grant permissions to registered app, so I have to use my own Azure credential.
Then I tried
var subscriptionClient = new Microsoft.Azure.Management.ResourceManager.Fluent.SubscriptionClient(new DefaultAzureCredential());
and
var subscriptionClient = new Microsoft.Azure.Management.ResourceManager.Fluent.SubscriptionClient(new UserPasswordCredential(username,password));
but none of them compiles.
The answer of question How to list subscriptions with Microsoft.Azure.ResourceManager? is almost the answer of my question, but I cannot add comment to ask more question about it.
I installed Microsoft.IdentityModel.Clients.ActiveDirectory version 3.13.2.870 and tried:
var ctx = new AuthenticationContext("https://login.microsoftonline.com/common");
but ctx doesn't have AcquireToken, it only has AcquireTokenAsync. Unfortunately the following code still doesn't work
var mainAuthRes = await context.AcquireTokenAsync(m_resource, m_clientId, new Uri(m_redirectURI), PromptBehavior.Always);
The compiler says the fourth parameter is wrong which means
context.AcquireTokenAsync(string resource, string client , Uri uri , PromptBehavior promptBehavior )
is not a valid method.
Is there any way to list subscriptions with my current azure credential (without registering app) using C#?
Try the code works for me, it uses the VisualStudioCredential of Azure.Identity to auth, it will list all the subscriptions in all the AAD tenants that you can access(the user account logged in VS).
using Azure.Core;
using Azure.Identity;
using Microsoft.Azure.Management.ResourceManager;
using Microsoft.Rest;
using System;
using System.Threading;
namespace ConsoleApp2
{
class Program
{
public static void Main(string[] args)
{
VisualStudioCredential tokenCredential = new VisualStudioCredential();
TokenRequestContext requestContext = new TokenRequestContext(new string[] { "https://management.azure.com" });
CancellationTokenSource cts = new CancellationTokenSource();
var accessToken = tokenCredential.GetToken(requestContext, cts.Token);
ServiceClientCredentials serviceClientCredentials = new TokenCredentials(accessToken.Token);
SubscriptionClient SubscriptionClient = new SubscriptionClient(serviceClientCredentials);
var tenants = SubscriptionClient.Tenants.List();
foreach (var tenant in tenants)
{
//Console.WriteLine(tenant.TenantId);
VisualStudioCredentialOptions visualStudioCredentialOptions = new VisualStudioCredentialOptions{ TenantId = tenant.TenantId };
VisualStudioCredential tokenCredential1 = new VisualStudioCredential(visualStudioCredentialOptions);
TokenRequestContext requestContext1 = new TokenRequestContext(new string[] { "https://management.azure.com" });
CancellationTokenSource cts1 = new CancellationTokenSource();
var accessToken1 = tokenCredential1.GetToken(requestContext, cts1.Token);
ServiceClientCredentials serviceClientCredentials1 = new TokenCredentials(accessToken1.Token);
SubscriptionClient SubscriptionClient1 = new SubscriptionClient(serviceClientCredentials1);
var subs = SubscriptionClient1.Subscriptions.List();
foreach (var sub in subs)
{
//Console.WriteLine(sub.DisplayName);
Console.WriteLine($"SubscriptionName : {sub.DisplayName}");
Console.WriteLine($"SubscriptionId : {sub.SubscriptionId}");
Console.WriteLine($"TenantId : {tenant.TenantId}");
Console.WriteLine($"State : {sub.State}");
Console.WriteLine();
}
}
}
}
}
You can try using the REST API Subscriptions - List.
GET https://management.azure.com/subscriptions?api-version=2020-01-01
Request Header:
Authorization: Bearer <access token>
Update:
The simplest way to get access token is open the link Subscriptions - List and sign in with your account.
Then click "try it" at the top right of the script.
You will find the access token in Request preview.
Specifically looking for a way to perform point in time restore to a new Database, preserve the original database; using Managed API instead of REST API or Templates.
Code I have so far:
public async Task CreateDatabaseFromRestorePointAsync(
string resourceGroupName, string serverName,
string databaseName, DateTime time) {
using (SqlManagementClient sqlMgmtClient = GetSqlManagementClient())
{
DatabaseInner myDb = await sqlMgmtClient.Databases.GetAsync(
resourceGroupName, serverName, databaseName);
var newDb = new DatabaseInner
{
Location = myDb.Location,
CreateMode = CreateMode.PointInTimeRestore,
// RestorePointInTime = time;
Edition = "Basic",
SourceDatabaseId = myDb.Id
};
var result = await sqlMgmtClient.Databases.CreateOrUpdateAsync(
resourceGroupName, serverName, "BackUpRestoreTestDb", newDb);
// Throws "The point in time was not specified for restoring live database...'"
}
}
Found the following:
This SO link How to restore an Azure SQL Database to point-in-time using Azure management libraries for .NET.
And same link references a new Database instead of a DatabaseInner. Cant find Database objects namespace.
Databases - Create or Update
Microsoft.Sql/servers/databases template reference.
Edit 1:
Tried the restore method specifically from Brando Zhang's answer but there are apparently namespace changes. I'm using:
.Net 4.6.1
Microsoft.Azure.Management.Sql version 1.6.0-preview
Microsoft.Azure.Management.Sql.Models
Microsoft.Azure.Management.Sql.Fluent version 1.2.0
Microsoft.Azure.Management.Sql.Fluent.Models
Getting the namespace could not be found for DatabaseCreateOrUpdateParameters, DatabaseCreateOrUpdateProperties, DatabaseCreateMode, DatabaseCreateOrUpdateResponse.
SqlManagementClient exists in both ..sql and ..slq.fluent namespaces both of which do not find namespace for .server in the line sqlMgmtClient.Servers.Get(resourceGroupName, serverName).Server;
Searched Microsoft's Azure Management Namespaces with no luck.
But google found DatabaseCreateOrUpdateParameters and its namespace on a spanish MSDN site, which links to above.
The confusion here is because there are 3 different API's:
Microsoft.Azure.Management.Sql version < 1.0
Microsoft.Azure.Management.Sql version >= 1.0 (API reference: https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.management.sql?view=azure-dotnet)
Microsoft.Azure.Management.Sql.Fluent, which is based on Microsoft.Azure.Management.Sql version >= 1.0 and is intended to be a more human-friendly design but does not have as much feature support as the base .Sql library. (API reference: https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.management.sql.fluent?view=azure-dotnet)
Brando's answer is for the #1 API. To update the code for the new API (#2), it should look like this:
// Create a database: configure create or update parameters and properties explicitly
Database newDatabaseParameters = new Database()
{
Location = currentServer.Location,
CreateMode = DatabaseCreateMode.PointInTimeRestore,
Edition = databaseEdition,
SourceDatabaseId = "/subscriptions/{yoursubscriptionid}/resourceGroups/{yourgroupid}/providers/Microsoft.Sql/servers/{sqlservername}/databases/{sqldatabasename}",
RestorePointInTime = DateTime.Parse("2017-09-22T02:32:08Z"),//Restore Point time
};
Database db = sqlMgmtClient.Databases.CreateOrUpdate(resourceGroupName, serverName, databaseName, newDatabaseParameters);
return db;
The major differences are:
There is no longer separate classes like DatabaseCreateOrUpdateParameters, DatabaseCreateOrUpdateProperties, DatabaseCreateOrUpdateResponse. There is just one class Database.
The properties of Database are "flattened" so there is no inner Properties to set.
According to your description, I suggest you could try to use this nuget package.
Microsoft Azure SQL Management Library
Then you could use below codes to achieve Point In Time Restore.
Code like this:
Notice, you need registry an application to get tenantId, applicationId, SecretKey, then with subscriptionId to get the authentication token.
About how to register, you could refer to these codes:
Main method:
var subscriptionId = "subscriptionId ";
var clientId = "clientId ";
var tenantId = "tenantId ";
var secretKey = "secretKey ";
var azureSqlDatabase = "azureSqlDatabase ";
var resourceGroup = "resourceGroup ";
var azureSqlServer = "azureSqlServer ";
var databaseEdition = DatabaseEditions.Standard;
var databasePerfLevel = "S1";
SqlManagementClient sqlManagementClient = new SqlManagementClient(new Microsoft.Azure.TokenCloudCredentials(subscriptionId, GetAccessToken(tenantId, clientId, secretKey)));
CreateOrUpdateDatabase(sqlManagementClient, resourceGroup, azureSqlServer, azureSqlDatabase, databaseEdition, databasePerfLevel);
The get auth token method:
static string GetAccessToken(string tenantId, string clientId, string secretKey)
{
var authenticationContext = new AuthenticationContext($"https://login.windows.net/{tenantId}");
var credential = new ClientCredential(clientId, secretKey);
var result = authenticationContext.AcquireTokenAsync("https://management.core.windows.net/",
credential);
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
var token = result.Result.AccessToken;
return token;
}
The restore method:
static DatabaseCreateOrUpdateResponse CreateOrUpdateDatabase(SqlManagementClient sqlMgmtClient, string resourceGroupName, string serverName, string databaseName, string databaseEdition, string databasePerfLevel)
{
// Retrieve the server that will host this database
Server currentServer = sqlMgmtClient.Servers.Get(resourceGroupName, serverName).Server;
// Create a database: configure create or update parameters and properties explicitly
DatabaseCreateOrUpdateParameters newDatabaseParameters = new DatabaseCreateOrUpdateParameters()
{
Location = currentServer.Location,
Properties = new DatabaseCreateOrUpdateProperties
{
CreateMode = DatabaseCreateMode.PointInTimeRestore,
//DatabaseEditions.Standard;
Edition = databaseEdition,
SourceDatabaseId = "/subscriptions/{yoursubscriptionid}/resourceGroups/{yourgroupid}/providers/Microsoft.Sql/servers/{sqlservername}/databases/{sqldatabasename}",
RestorePointInTime = DateTime.Parse("2017-09-22T02:32:08Z"),//Restore Point time
//S1
RequestedServiceObjectiveName = databasePerfLevel
}
};
DatabaseCreateOrUpdateResponse dbResponse = sqlMgmtClient.Databases.CreateOrUpdate(resourceGroupName, serverName, databaseName, newDatabaseParameters);
return dbResponse;
}
Result:
How to enumerate Azure subscriptions and tenants programmatically? This is related to my previous question Login-AzureRmAccount (and related) equivalent(s) in .NET Azure SDK.
Basically I try to replicate the behavior of Login-AzureRmAccount and Get-AzureRmSubscription in desktop or a console application. Thus far I've figured out MSAL seems to always require client ID and tenant ID, so there needs to be some other library to acquire those from. After this I would like to go about creating a service principal programmatically using the most current library, but I suppose that is a subject for further investigation (and questions if needed).
Actually, the Login-AzureRmAccount and Get-AzureRmSubscription use the Microsoft Azure PowerShell app to operate the Azure resource through Resource Manager REST APIs.
To simulate the same operations using REST as PowersShell commands, we can also use this app. However since this app is register on Azure portal(not the v2.0 app) so we are not able to acquire the token using this app via MSAL. We need to use Adal instead of MSAL.
Here is a code sample to list the subscriptions using admin account via Microsoft.WindowsAzure.Management using this app for your reference:
public static void ListSubscriptions()
{
string authority = "https://login.microsoftonline.com/common";
string resource = "https://management.core.windows.net/";
string clientId = "1950a258-227b-4e31-a9cf-717495945fc2";
Uri redirectUri = new Uri("urn:ietf:wg:oauth:2.0:oob");
AuthenticationContext authContext = new AuthenticationContext(authority);
var access_token = authContext.AcquireTokenAsync(resource, clientId, redirectUri, new PlatformParameters (PromptBehavior.Auto)).Result.AccessToken;
var tokenCred = new Microsoft.Azure.TokenCloudCredentials(access_token);
var subscriptionClient = new SubscriptionClient(tokenCred);
foreach (var subscription in subscriptionClient.Subscriptions.List())
{
Console.WriteLine(subscription.SubscriptionName);
}
}
Update:
string resource = "https://management.core.windows.net/";
string clientId = "1950a258-227b-4e31-a9cf-717495945fc2";
string userName = "";
string password = "";
HttpClient client = new HttpClient();
string tokenEndpoint = "https://login.microsoftonline.com/common/oauth2/token";
var body = $"resource={resource}&client_id={clientId}&grant_type=password&username={userName}&password={password}";
var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded");
var result = client.PostAsync(tokenEndpoint, stringContent).ContinueWith<string>((response) =>
{
return response.Result.Content.ReadAsStringAsync().Result;
}).Result;
JObject jobject = JObject.Parse(result);
var token = jobject["access_token"].Value<string>();
client.DefaultRequestHeaders.Add("Authorization", $"bearer {token}");
var subcriptions = client.GetStringAsync("https://management.azure.com/subscriptions?api-version=2014-04-01-preview").Result;
Console.WriteLine(subcriptions);
I am new to Azure management libraries for .net. How can we enumerate VM instance sizes available with respect to subscription or in general using Azure Management libraries for .Net or Rest APIs?
Please suggest.
You can get a list of VM sizes for a region by calling
https://management.azure.com/subscriptions/{subscription-id}/providers/Microsoft.Compute/locations/{location}/vmSizes?api-version={api-version}
As documented here - List all available virtual machine sizes in a region
There is also a .Net Class for the same, but I've not found any examples of it being used - documented here - VirtualMachineSizeOperationsExtensions.List
You can get list of VM sizes by region fillter
AuthenticationContext authenticationContext = new AuthenticationContext("https://login.windows.net/tenantdomainname.onmicrosoft.com"]);
UserCredential uc = new UserCredential(authusername,authpassword);
token = authenticationContext.AcquireToken("https://management.core.windows.net/", nativetenantid, uc);
var credentials = new TokenCredentials(token);
var computeClient = new ComputeManagementClient(credentials) { SubscriptionId = subscriptionid};
var virtualMachineSize = computeClient.VirtualMachineSizes.List(region_name).ToList();
you must need create one native client api on Azure Active Directory for token base authentication otherwise you can also use certification base authentication for client authorization.
i am using Microsoft.Azure.Management.Compute.dll, v10.0.0.0 for compute resources.
you can download here: https://www.nuget.org/packages/Microsoft.Azure.Management.Compute/13.0.4-prerelease
You can get list of VM Size by using Certificate Base Authentication
Get Certificate method
private static X509Certificate2 GetStoreCertificate(string subscriptionId, string thumbprint)
{
List<StoreLocation> locations = new List<StoreLocation>
{
StoreLocation.CurrentUser,
StoreLocation.LocalMachine
};
foreach (var location in locations)
{
X509Store store = new X509Store(StoreName.My, location);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certificates = store.Certificates.Find(
X509FindType.FindByThumbprint, thumbprint, false);
if (certificates.Count == 1)
{
return certificates[0];
}
}
finally
{
store.Close();
}
}
throw new ArgumentException(string.Format("A Certificate with Thumbprint '{0}' could not be located.",thumbprint));
}
here i describe same way to get VM size
private static X509Certificate2 Certificate = GetStoreCertificate(Your-subscriptionid,Your-thumbprint);
Microsoft.Azure.CertificateCloudCredentials credentials = new Microsoft.Azure.CertificateCloudCredentials(Your-subscriptionid, Certificate);
var computeClient = new ComputeManagementClient(credentials) { SubscriptionId = Your-subscriptionid};
var virtualMachineSize = computeClient.VirtualMachineSizes.List(Your-region_name).ToList();
Is it possible to change the app settings for a website from the app itself?
This is not meant to be an everyday operation, but a self-service reconfiguration option. A non-developer can change a specific setting, which should cause a restart, just like I can do manually on the website configuration page (app setting section)
You can also use the Azure Fluent Api.
using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
...
public void UpdateSetting(string key, string value)
{
string tenantId = "a5fd91ad-....-....-....-............";
string clientSecret = "8a9mSPas....................................=";
string clientId = "3030efa6-....-....-....-............";
string subscriptionId = "a4a5aff6-....-....-....-............";
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/xxx/resourceGroups/xxx/providers/Microsoft.Web/sites/xxx"; //Get From WebApp -> Properties -> Resource ID
var webapp = _azure.WebApps.GetById(appResourceId);
//Set App Setting Key and Value
webapp.Update()
.WithAppSetting(key, value)
.Apply();
}
It wasn't that hard once I found the right lib to do it, Microsoft Azure Web Sites Management Library.
var credentials = GetCredentials(/*using certificate*/);
using (var client = new WebSiteManagementClient(credentials))
{
var currentConfig = await client.WebSites.GetConfigurationAsync(webSpaceName,
webSiteName);
var newConfig = new WebSiteUpdateConfigurationParameters
{
ConnectionStrings = null,
DefaultDocuments = null,
HandlerMappings = null,
Metadata = null,
AppSettings = currentConfig.AppSettings
};
newConfig.AppSettings[mySetting] = newValue;
await client.WebSites.UpdateConfigurationAsync(webSpaceName, webSiteName,
newConfig);
}
Have you read into the Service Management REST API? The documentation mentions that it allows you to perform most the actions that are available via the Management Portal programmatically.
In addition to Diego answer, to use the Azure Management Librairies within a WebApp (WebSites and/or WebJobs), you need to configure SSL which is a little bit tricky:
Using Azure Management Libraries from Azure Web Jobs