天道酬勤,学无止境

Storing Azure Vault Client ID and Client Secret

I am using .NET Core 2.0 and ASP.NET Core 2.0 for application development. The "test" application is a .NET Core Console application. The core code I am writing is a class library. Once proper testing. I choose to do this since I won't be putting this to use for awhile (it's replacing older ASPNET code).

Anyway, since I have to work with a LOT of API keys for various services I decided to use Microsoft Azure Key Vault for storing the keys. I have this all setup and understand how this works. The test application uses a test Azure account so it's not critical. And since this is replacing legacy code and it's in the infancy, I am the sole developer.

Basically, I'm running into this issue. There's not too much information on Azure Key Vault from what I can see. A lot of examples are storing the Client ID and Secret in a plain text json file (for example: https://www.humankode.com/asp-net-core/how-to-store-secrets-in-azure-key-vault-using-net-core). I really don't understand how this can be secure. If someone were to get those keys they could easily access stored information Azure, right?

The Microsoft MSDN has a powershell command that grants access (I lost the original link, this is closest I can find: https://www.red-gate.com/simple-talk/cloud/platform-as-a-service/setting-up-and-configuring-an-azure-key-vault/) My development operating system is Windows 10 and my primary server operating system is Debian.

How would I approach this?

评论

Yes, you are right, the plain text config file could be used only during development, not for production purpose. And in general, available options depend on where and how you host an App.

If you have an Azure Web App, you have at least next built-in options (from the documentation):

  • add the ClientId and ClientSecret values for the AppSettings in the Azure portal. By doing this, the actual values will not be in the web.config but protected via the Portal where you have separate access control capabilities. These values will be substituted for the values that you entered in your web.config. Make sure that the names are the same.

  • authenticate an Azure AD application is by using a Client ID and a Certificate instead of a Client ID and Client Secret. Following are the steps to use a Certificate in an Azure Web App:

    • Get or Create a Certificate
    • Associate the Certificate with an Azure AD application
    • Add code to your Web App to use the Certificate
    • Add a Certificate to your Web App

You may also find an approach that uses env variables to store credentials. This may be OK only if you can guarantee that it's not possible to do a snapshot of env variable on prod machine. Look into Environment Variables Considered Harmful for Your Secrets for more details.


And the last one thing: there is also a technic that based on the idea, that you need to store/pass only a ClientSecret value while ClientId should be constructed based on machine/container details where the App is hosted (e.g. docker container id). I have found an example for Hashicorp Vault and an App hosted on AWS, but the general idea is the same: Secret management with Vault

In addition to the first answer, with the context of running applications on Azure VM, instead of using client_secret to authenticate, you can use client certificate authentication as explained in this documentation: Authenticate with a Certificate instead of a Client Secret.

In the picture above:

  • Application is authenticating to AAD by proving that it has the private key of the certificate (which is basically stored in CNG if you are using Windows).
  • Application get back the access_token and then use it to access the Key Vault.

The developer does not need to know the private key value of the certificate in order for their app to be successfully authenticated. Instead, they only need to know the location of the imported pfx (a container for private key and its certificate) in the Certificate Store.

At least on Windows, you as secret administrator can convert the private key and the certificate into pfx format which is password protected, and then deploy it into the Windows Certificate store. This way no one could know the private key unless they know the password of the pfx file.


The other approach specifics for Azure Compute, is to use Azure Managed Service Identity. Using Azure MSI, Azure will automatically assign your resources such as VM with an identity / Service Principal, and you can fire requests at a specific endpoint that are only accessible by your resource to get the access_token. But be wary that Azure MSI are still under public preview, so please review the known issues before using it.

The picture above explain how Azure Resource Manager assign a Service Principal identity to your VM.

  • When you enable MSI in a VM, Azure will create a service principal in your AAD.
  • Azure will then deploy a new MSI VM extension to your VM. This provides an endpoint at http://localhost:50432/oauth2/token to be used to get the access_token for the service principal.
  • You can then use the access_token to access the resources such as Key Vault which authorize the service principal access.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 如何在Azure Key Vault中序列化和反序列化PFX证书?(How to serialize and deserialize a PFX certificate in Azure Key Vault?)
    问题 我有一堆字符串和pfx证书,我想将它们存储在Azure Key保管库中,只有允许的用户/应用程序才能获取它们。 将字符串存储为Secret并不难,但是如何以一种可以序列化证书的方式来检索它并在C#中将其反序列化为X509Certificate2对象呢? 我试图将其存储为密钥。 这是Azure Powershell代码 $securepfxpwd = ConvertTo-SecureString -String 'superSecurePassword' -AsPlainText -Force $key = Add-AzureKeyVaultKey -VaultName 'UltraVault' -Name 'MyCertificate' -KeyFilePath 'D:\Certificates\BlaBla.pfx' -KeyFilePassword $securepfxpwd 但是,当我尝试使用GetKeyAsync方法获取它时,我无法使用它。 回答1 这是适合您的PowerShell脚本。 替换文件路径,密码,文件库名称,机密名称。 $pfxFilePath = 'C:\mycert.pfx' $pwd = '123' $flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]
  • How to add Azure Python SDK exceptions to try/except statements?
    I'm new to Python. I have a working, monolithic Python program that I'm breaking into individual Python functions. I'd like to use the try: - except: pattern to catch specific exceptions for each function. Example: Create a Key Vault client and retrieve a secret from Key Vault import logging from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient credentials = DefaultAzureCredential() def create_kv_client(kv_name, credentials): kv_uri = 'https://' + kv_name + '.vault.azure.net' kv_client = SecretClient(vault_url=kv_uri, credential=credentials) return
  • 如何保护web.config中存储的密码?(How can I secure passwords stored inside web.config?)
    问题 我在web.config文件中添加了以下设置,以启动对外部系统的API调用。 因此,我将按以下方式存储API URL +用户名+密码:- <appSettings> <add key="ApiURL" value="https://...../servlets/AssetServlet" /> <add key="ApiUserName" value="tmsservice" /> <add key="ApiPassword" value="test2test2" /> 然后在我的操作方法中,当构建Web客户端时,我将引用这些值,如下所示: public ActionResult Create(RackJoin rj, FormCollection formValues) { XmlDocument doc = new XmlDocument(); using (var client = new WebClient()) { var query = HttpUtility.ParseQueryString(string.Empty); foreach (string key in formValues) { query[key] = this.Request.Form[key]; } query["username"] = System.Web.Configuration
  • KeyVault GetSecretAsync 永远不会返回(KeyVault GetSecretAsync never returns)
    问题 在 Web 应用程序中使用 KeyVault 的示例代码包含以下代码: public static async Task<string> GetSecret(string secretId) { var secret = await keyVaultClient.GetSecretAsync(secretId); return secret.Value; } 我已将示例中包含的KeyVaultAccessor对象合并到我的应用程序中以对其进行测试。 该调用作为对我的 Web api 控制器方法之一的查询的一部分执行: var secret = KeyVaultAccessor.GetSecret("https://superSecretUri").Result; 不幸的是,调用永远不会返回并且查询无限期地挂起...... 可能是什么原因,因为坦率地说我不知道​​从哪里开始......? 回答1 这是我在博客中完整描述的常见死锁问题。 简而言之, async方法试图在await完成后返回到 ASP.NET 请求上下文,但该请求一次只允许一个线程,并且该上下文中已经有一个线程(在调用Result )。 所以任务在等待上下文空闲,线程阻塞上下文直到任务完成:死锁。 正确的解决方案是使用await而不是Result : var secret = await
  • Exception while fetching value of first key vault secret for the application
    In my application I am getting exception when my application fetches value of first key vault secret. The exception I am only getting when I turn on "Common Language Run-time Exceptions" from exception settings. Exception that I am getting is- Microsoft.Rest.TransientFaultHandling.HttpRequestWithStatusException: 'Response status code indicates server error: 401 (Unauthorized).' StackTrace:- at Microsoft.Rest.RetryDelegatingHandler.<>c__DisplayClass11_0.<<SendAsync>b__1>d.MoveNext() My code to fetch the key vault secret is given below- public async Task<string> GetSecretValue(string clientId
  • How to set a secret in Azure Key Vault from a local asp.net application
    I have a local asp.net core 3.1 application that I want to set a secret in an Azure Key Vault. The following is the code I used from Microsoft: string secretName = "xxSecret"; string keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME"); var kvUri = "https://" + keyVaultName + ".vault.azure.net"; var secretClient = new SecretClient(new Uri(kvUri), new DefaultAzureCredential()); string secretValue = "test"; secretClient.SetSecret(secretName, secretValue); KeyVaultSecret secret = secretClient.GetSecret(secretName); When I try to set a secret, I get the following error in Postman
  • Can't Access Azure Key Vault from desktop console app
    I am having trouble accessing a secret from an Azure key vault. I suspect the problem is that I don't adequately understand the terminology, so the arguments I'm supplying to various API calls are wrong. Here's the basic code I'm using: protected async Task<string> GetCommunityKeyAsync( UserConfiguration user ) { var client = new KeyVaultClient( new KeyVaultClient.AuthenticationCallback( GetAccessTokenAsync ), new HttpClient() ); // user.VaultUrl is the address of my key vault // e.g., https://previously-created-vault.vault.azure.net var secret = await client.GetSecretAsync( user.VaultUrl,
  • Read Azure key vault secret through MSI in Java
    I am trying to read secret in Azure Key Vault through Managed Service Identity (MSI) in Java. I want token to access the key vault through MSI. There are references available for .net to do this but did not find anything in Java. I don't want to do this through Client id/secret key or certificates. I want something in Java that is close to following .net code using Microsoft.Azure.KeyVault; using Microsoft.Azure.Services.AppAuthentication; AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(); try { var keyVaultClient = new KeyVaultClient(new KeyVaultClient
  • VSTS Build Pipeline: Test fails connecting to Azure Key Vault
    I am trying to use VSTS (now Azure DevOps) to do a CI/CD pipeline. For my build pipeline, I have a very basic setup involving doing a restore, build, test, and publish steps. For my test step, I have it setup to run two test projects - one unit test project and one integration test project. I have my Key Vault access policy setup to provide access to both myself and Azure Devops. When I run my tests locally using visual studio, as I am logged into the same account which has access to azure key vault, I can run the tests without any errors. My application is configured to access key vault using
  • 存储非结构化数据之利器-minio
    一、minio简介 Minio 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。 Minio是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。(引自https://docs.min.io/docs/minio-quickstart-guide.html ) 二、minio-server单节点部署 2.1、下载minio wget https://dl.minio.io/server/minio/release/linux-amd64/minio chmod +x minio 2.2、将minio移动到/usr/local/bin目录 mv minio /usr/local/bin/ 2.3、编辑配置文件 cat <<EOT >> /etc/default/minio # Volume to be used for MinIO server. MINIO_VOLUMES="/data/minio/" # Use if you want to run MinIO on a custom port. #MINIO_OPTS="-
  • How to solve azure keyvault secrets (Unauthorized) AKV10032: Invalid issuer. error in Python
    I am using the azure-keyvault-secrets package to manage my resources secrets in Python 3.8, developping in PyCharm. But when I am running the following: import os from azure.keyvault.secrets import SecretClient from azure.identity import DefaultAzureCredential VAULT_URL = os.environ["VAULT_URL"] credential = DefaultAzureCredential() client = SecretClient( vault_url=VAULT_URL, credential=credential ) client.set_secret('my-secret-name', 'my-secret-value') I get the following error: HttpResponseError: azure keyvault secrets (Unauthorized) AKV10032: Invalid issuer. error I have set the environment
  • 如何以编程方式将应用程序添加到Azure AD?(How to add application to Azure AD programmatically?)
    问题 我想在Azure AD中自动创建应用程序,并取回Azure AD生成的客户端ID。 是否有PowerShell命令集可以执行此操作? 除了管理控制台之外,还有其他方法,例如执行此操作的API吗? 你能给我指出一个例子吗? 谢谢! 回答1 您可以通过多种方式在AAD中以编程方式创建应用程序。 我将简要介绍执行此操作的两种不同方法:PowerShell CMDLET和Graph API。 通常,我强烈建议为此使用Graph API。 电源外壳: 有一些运行的不同模块可以创建AAD应用程序/服务主体。 如果需要在租户中创建新的应用程序对象,则可以使用Azure PowerShell进行以下调用: https://msdn.microsoft.com/zh-CN/library/mt603747.aspx PS C:\> New-AzureRmADApplication -DisplayName "NewApplication" -HomePage "http://www.Contoso.com" -IdentifierUris "http://NewApplication" 如果需要在租户中为应用程序创建服务主体,则可以使用Azure AD PowerShell: https://msdn.microsoft.com/zh-CN/library/azure/jj151815
  • Azure AAD - 受众无效(Azure AAD - The audience is invalid)
    问题 我创建了一个使用 azure 活动目录保护的 webapi。 我现在需要对此进行测试并尝试使用带有授权标头的 fiddler。 我正在尝试使用以下代码生成令牌。 Target obj = (Target)cmbTarget.SelectedItem; AuthenticationResult authenticationResult; string aadInstance = obj.AADInstance; // "https://login.windows.net/{0}"; string tenant = obj.Tenant; //"rudderless.onmicrosoft.com"; string apiResourceId = obj.ApiResourceId; //"15b4ac7f-23a8-4958-96a5-64159254690d"; string clientId = obj.ClientId; // "47cdc6c3-226a-4c38-b08e-055be8409056"; Uri redirectUri = new Uri(obj.RedirectUri); //new Uri("http://nativeclient"); string authority = string.Format(aadInstance, tenant)
  • Are the Azure Client Id, Tenant, and Key Vault URI considered secrets?
    I'm getting up to speed with Azure and trying to follow best practices for securing my WPF and Xamarin.Forms apps. I'm using Azure AD for authentication and Key Vault for my secrets. What about my Client Id and Tenant settings? These are required to make the initial connection to Azure to log in. The endpoint URI is also required to make a call to the Key Vault. Are the Client Id, Tenant, Key Vault endpoint considered secrets or am I over thinking this. I understand without authenticating, no one can access or make use of these. What about checking these into Source Control? Is this Ok
  • Azure - authenticating to KeyVault using Service Principle returns an Unauthorized exception
    I'm trying to access KeyVault from an .net Core console application, using a Service Principle (I have the App Id and App Secret). Here's my code: var client = new KeyVaultClient(GetAccessToken); var secret = client.GetSecretAsync("https://{keyvaultName}.vault.azure.net", "MySecret").Result; Which calls back to this function: private static async Task<string> GetAccessToken(string authority, string resource, string scope) { var context = new AuthenticationContext(authority, TokenCache.DefaultShared); var credential = new ClientCredential(clientId: appId, clientSecret: appSecret); var
  • 使用 Adal 代表用户访问 Azure KeyVault(Using Adal for accessing the Azure KeyVault on behalf of a user)
    问题 以下是在控制台应用程序和 ClientID 中,RedirectUri 来自在 azure 活动目录中创建的本机应用程序。 var authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}","common"),new FileCache()); var token = authContext.AcquireToken("https://management.core.windows.net/", ClientID, RedirectUri, PromptBehavior.Auto); 我现在有了与管理 api 交谈的令牌。 using (var client = new KeyVaultManagementClient(new TokenCloudCredentials(SubscriptionId, token.AccessToken))) { var a = client.Vaults.List(resourceGroup, 10); foreach(var vault in a.Vaults) { var vaultInfo = client.Vaults.Get(resourceGroup, vault.Name); Console.WriteLine
  • Using Adal for accessing the Azure KeyVault on behalf of a user
    The following is in a console application and ClientID, RedirectUri is from the created native app in azure active directory. var authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}","common"),new FileCache()); var token = authContext.AcquireToken("https://management.core.windows.net/", ClientID, RedirectUri, PromptBehavior.Auto); I now have the token for talking with management api. using (var client = new KeyVaultManagementClient(new TokenCloudCredentials(SubscriptionId, token.AccessToken))) { var a = client.Vaults.List(resourceGroup, 10); foreach(var vault
  • How is a keyvault more secure than standard storage?
    I am trying to understand the security benefits that Azure Key Vault would offer (or equally AWS KMS) I understand the benefits of key management, of being able to easily rotate, change, audit key access. What perplexes me a little though is how it is more secure. As I understand it, if I develop a web application and want to protect my connection string (for instance) I can create a key pair in Key Vault and save it there. I then create an application in AAD, and use the client ID/Secret/URI to authenticate to Key Vault to obtain my connection string. There is also the possible benefit of
  • Getting Unathorized when trying to get a secret from Azure key Vault
    I'm using Microsoft.Azure.keyVault trying to get a secret from a key vault in Azure. I've registered an application as both Native and Web API. Logging on to the AD is successful (can confirm this by getting a valid AccessToken on AuthenticationContext.AcquireTokenAsync). In Azure AD both applications have been given Access Control (IAM) and Access Policies in the Key Vault. I have confirmed that the Key Vault Base Url and the Secret Name are correct but when making the following call var sec = kv.GetSecretAsync("https://xxxxxxx.vault.azure.net", "xxsecretnamexx").GetAwaiter().GetResult(); I
  • Azure密钥保管库:访问被拒绝(Azure key vault: access denied)
    问题 我具有以下用于从Azure密钥保管库获取机密的代码: public static async Task<string> GetToken(string authority, string resource, string scope) { var authContext = new AuthenticationContext(authority); ClientCredential clientCred = new ClientCredential(...); //app id, app secret AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred); if (result == null) throw new InvalidOperationException("Failed to obtain the JWT token"); return result.AccessToken; } public static string GetSecret(string secretName) { KeyVaultClient keyVaultClient = new KeyVaultClient(GetToken); try { return