I want to store a development-time secret somewhere outside of my code repository, that developers are able to use without any manual tasks. (As close to Build, Run, and it will just work).
The secrets have to be configured in the aspnetcore Configuration Builder like this:
var builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json";
builder.AddDevelopmentSecrets(...);
The official recommendation by the aspnetcore team seems to be to use the Secret Manager Tool. But this requires every developer to configure the secrets manually. For example, they'd have to run dotnet user-secrets set key value for every secret.
The 2nd thing I looked at was Azure KeyVault. This seemed ideal, because I'd only have to call builder.AddAzureKeyVault(...). The only problem is that I'd have to store the clientId and clientSecret to access the keyvault somewhere.
Ideally I want something that the AWS Toolkit for Visual Studio extension does. Once the extension is installed, you simply login with your AWS credentials and the extension simply injects your credentials into every official AWS call that is used.
Does Azure have anything like this? Something that allows me to inject (or access) my Azure credentials, so they can be used in the call to AddAzureKeyVault(...)? And if not, what's the closest solution that comes close to this?
Azure AD Managed Service Identity can help here. The implementation based on my suggestion:
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
builder.AddAzureKeyVault("https://x.vault.azure.net/", keyVaultClient, new DefaultKeyVaultSecretManager());
Now you can sign in to the Azure CLI 2.0 and those credentials will be automatically used to access KeyVault.
You can read more about MSI here: https://joonasw.net/view/azure-ad-managed-service-identity
To extend on #juunas his answer: Visual Studio 15.5 was just released which makes this even easier. If you've logged onto your Azure account from Visual Studio (and you have installed the currently in preview Azure Services Authentication Extension), Visual Studio will simply take care of the Azure KeyVault authentication.
You only need to specify the KeyVault url in launchSettings.json under the environement variables. No need for Azure CLI, or the AppAuthentication library.
This even works on the full .NET Framework, not just ASP.NET Core.
See:
General: https://blogs.msdn.microsoft.com/visualstudio/2017/11/17/managing-secrets-securely-in-the-cloud/
ASP.NET Core Example: https://github.com/CawaMS/aspnetcore-msi-keyvault
Related
The newest versions of MassTransit started using Azure.Identity package as a replacement for Microsoft.Azure.SericeBus.
I use Hybrid Identity to authenticate on premise service with the Azure Service Bus. It works well with TokenProvider.CreateManagedIdentityTokenProvider in Microsoft.Azure.SericeBus. However, after the switch to Azure.Identity package neither DefaultAzureCredential nor ManagedIdentityCredential work. I get an error saying that "Service request failed: 401 (Unathorized). Manage,EntityRead required for this operation".
I suspect that the new Azure.Identity package only works with Azure hosted apps and not with my on prem hosted service. But since it worked fine with the old package I am trying to figure out if I can make it work.
Any ideas if it is possible to use Hybrid Identity for accessing ASB from on prem service with recent MassTransit package >7.3.0?
I'm the author the of the original MassTransit change that brought the Service Bus SDK to v7.
There are differences in the underlying auth libraries.
TokenProvider.CreateManagedIdentityTokenProvider uses the AzureServiceTokenProvider under the hood. There's two possible paths when setting up the underlying token providers:
If AzureServicesAuthConnectionString is set as an environment variable, it will be used to configure the auth settings.
Else, there's a prioritized list of non-interactive providers (Msi, VS, Azure CLI, WindowsAuth (when using the full framework))
If AzureServicesAuthConnectionString environment variable is not set, DefaultAzureCredential appears to be nearly identical for the underlying token providers. If it is set, it may be a difference in the parsing of the environment variable. The DefaultAzureCredential uses an EnvironmentCredential as a credential, but it expects separate variables for tenant ID, client ID, etc (see docs for specifics).
Unfortunately, I'm not familiar with Hybrid Identity so these comments are solely based on my understanding of the Azure libraries.
I created Managed Application for Azure Marketplace. And I use some secret data during deploy app to user subscription. Is it secure putting this data to file mainTemplate.json? And if not, what variants exists?
Try this: https://learn.microsoft.com/en-us/azure/managed-applications/key-vault-access
The template files for a managed app in the marketplace are only secured by obscurity (you need to guess at what the URL is (and it contains a guid)). So for added security, put the secrets in KV and reference them from there.
not a good practice. Instead use Azure key vault as per your scenario.
Refer : https://learn.microsoft.com/en-us/azure/key-vault/key-vault-whatis
This question refers to the article:
https://learn.microsoft.com/en-us/azure/app-service/app-service-managed-service-identity
I'm trying to figure out how I can simulate using the service principal that is generate for my azure application to work locally.
I followed the article and when I deploy azure function to azure and run it from there, I'm able to successfully use the MSI_ENDPOINT and the MSI_SECRET to successfully get the token. However, when i run the same deployment locally it fails. I use the exact same MSI_SECRET and change the MSI_ENDPOINT to the Domain that I use to the azure function endpoint.
Example: On azure the MSI_ENDPOINT = http://127.0.0.1:41831 and locally it is http://localhost:7071 (http://0.0.0.0:7071
However, when I run it locally I get a 404 error with the request. The request is http://0.0.0.0:7071/MSI/token?resource=https://vault.azure.net&api-version=2017-09-01 with the secret in the header. Exact same params with the working one loaded on azure except for the MSI_ENDPOINT.
Any advice on how to address this so I can run and test locally?
Using the Microsoft.Azure.Services.AppAuthentication library for .NET
for .NET applications and functions, the simplest way to work with a
managed identity is through the
Microsoft.Azure.Services.AppAuthentication package. This library will
also allow you to test your code locally on your development machine,
using your user account from Visual Studio, the Azure CLI, or Active
Directory Integrated Authentication. For more on local development
options with this library, see the
Microsoft.Azure.Services.AppAuthentication reference. This section
shows you how to get started with the library in your code.
Add references to the Microsoft.Azure.Services.AppAuthentication and Microsoft.Azure.KeyVault NuGet packages to your application.
However, this library is only available in .net which i'm not using and does not really explain how you would do it via REST call.
Thanks!
As far as I understand, MSI via REST works for you in the cloud, but not locally.
Unfortunately, it seems this is currently not easily possible when you can't use the AppAuthentication library. See this GitHub suggestion.
So if you don't want to hack some debug code into your production code, you probably need to host a "custom MSI proxy" locally which just performs the classic authentication via client credentials (appId + secret) to return the token.
curl -d "grant_type=client_credentials&client_id=<removed_for_security>&client_secret=<removed_for_security>&resource=https%3A%2F%2Fvault.azure.net" https://login.microsoftonline.com/<removed_for_security>/oauth2/token
Note that I added the KeyVault as the resource parameter. See your built MSI URL - http://0.0.0.0:7071/MSI/token?resource=https://vault.azure.net&api-version=2017-09-01
I'm trying to implement Azure KeyVault in my Azure Functions app following this article: https://medium.com/statuscode/getting-key-vault-secrets-in-azure-functions-37620fd20a0b
In the article, the function app is set to use Managed Service Identity (MSI) so that we don't have to use a secret to get a token in order to connect to Azure KeyVault. Because that would kind of defeat the purpose of using Azure KeyVault.
As I understand it, an Azure app can be registered to use MSI so that other Azure resources recognize it directly, thus simplifying the connection process by eliminating the need to get a token, etc.
However, as I debug my Azure functions app, I'm unable to connect to Azure KeyVault to retrieve the necessary secrets.
I feel maybe that's happening because the functions app is running locally during debug and not on Azure.
Would this be the reason why I'm unable to connect to KeyVault?
Yes unfortunately MSI will only get a token when running inside of the Azure Functions service. I did update my sample about a week ago with a new #if region I use to pull secret from local variables if in DEBUG mode.
https://github.com/jeffhollan/functions-csharp-keyvault-eventhub/blob/master/ScaleTestV1_NoHost/Http.cs
There is a better solution available now for this problem of using Managed Service Identity during local development in debug mode (at least for .NET applications and functions).
You can use Microsoft.Azure.Services.AppAuthentication package.
Relevant Code Sample.. (from references below)
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.KeyVault;
// ...
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://vault.azure.net");
// OR
var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
How to use managed identities for App Service and Azure Functions
Microsoft.Azure.Services.AppAuthentication Reference
The Microsoft.Azure.Services.AppAuthentication for .NET library
simplifies this problem. It uses the developer's credentials to
authenticate during local development. When the solution is later
deployed to Azure, the library automatically switches to application
credentials.
For further details about, how AzureServiceTokenProvider fetches tokens using Visual Studio, Azure CLI or Azure AD Integrated Authentication.. Read here
As an addendum of Rohit Saigal answer please notice following:
Locally development within Visual Studio using Azure Key Vault service depends on
"Azure Services Authentication Extension" https://marketplace.visualstudio.com/items?itemName=chrismann.MicrosoftVisualStudioAsalExtension#overview
which is integrated into Visual Studio since version 15.6 onward and don't need to be installed separately.
Check Visual Studio/Tools/Options/Azure Services Authentication to see which account you use to auth within Azure services, and set appropriate.
My problem is that I have a NuGet server on an Azure website using Azure AD for auth. It works as expected if I hit the NuGet URL in Chrome (requires the login, which accepts appropriate credentials), but if I try to access it in Visual Studio 2013 (through manage NuGet packages) it won't accept the account/password as appropriate credentials (the prompt just pops up again). My approach was as follows:
With the goal of creating a simple internal NuGet server, I largely followed the instructions in this article to deploy one on an Azure website: http://www.codeproject.com/Articles/872230/Create-Your-Own-Private-NuGet-Server-in-Windows-Az
The NuGet server works just fine, but I wanted to add some basic auth since we'll be hosting some of our code there. I decided to try to use Azure AD for this. I added a couple Microsoft accounts (mine and a coworker's) to our otherwise empty default Azure active directory. Through the management portal, I then selected the 'configure' tab in the website dashboard and added the default directory in the auth section.
Since the developers who will be pulling down our packages will do so through Visual Studio, I need to figure this out or find an alternative. I would like (if possible) to avoid writing my own auth module, since this feature is supposed to be baked into Azure.
It turns out that NuGet does not currently support Azure AD. However, they are working on it and progress can be tracked here: https://github.com/NuGet/Home/issues/708