Using ASP.Net Core v2.2 ProtectKeysWithAzureKeyVault() data protection - .net-core

Using ASP.NET Core 2.2 I'm trying to configure data protection such that I store the keyring in Azure Blob Storage and protect the keyring with a key stored in KeyVault.
In my ConfigureServices() method I have:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("myblob-sasuri"))
.ProtectKeysWithAzureKeyVault(keyVaultClient, "key-identifier-uri");
}
All looks good, but I am confounded with Forbidden errors in accessing the keyvault. I can't figure out if I have somehow screwed up the key identifier (doubtful) or the keyVaultClient, or the permissions.
I suspect permissions, but nowhere do the docs tell me what permissions the client needs.
Anyone made this work successfully?

Through experimentation I have learned that the KeyVault access policy must have the "Unwrap Key" permission enabled in the Cryptographic Operations section of Key Permissions. So, the service principal you grant access to the KeyVault must be granted that one specific permission in your access policies. We ran into problems because we had not enabled that, we had just Encrypt and Decrypt permissions enabled. This should be documented, I added feedback to the doc here: https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-2.2

Related

Access Key Vault for a Service Fabric application using Azure Active Directory

I have an application that runs in a Service Fabric(SF) cluster and I wan't to access Key Vault from it.
The cluster hosts a number of applications and I want to give access to a Key Vault for my application without giving access to the other applications. By default an application runs under the same user as the SF cluster, but each applicatiuon has it's own unique name, mine has the name fabric:/application1.
My question is, is it possible to create an Active Directory application account for fabric:/application1 and grant access to the key vault?
I know it is possible to use the RunAs options in the SF manifest, but that requires me storing an encrypted password in the manifest/source code and I want to try and avoid this if possible.
AFAIK,
The only way to have this flexibility is using ClientID & Secret or Service Principal certificates and each application manage their own credentials.
Service Principal Certificate is already integrated to AD, but does not require the application, the user or the Host to be part of the domain, the only requirement is setup an user on AD to grant the permissions on Keyvault.
There are other solutions using AD integration, like Managed identities for Azure resources(Former: Managed Service Identity) but I am not sure if you are able to restrict access per application like you described, because the MI add this as a service in the node, so technically other applicaitons would have access as well, worth a try to validate if you can restrict this.
If you want to try this approach, you can use with Microsoft.Azure.Services.AppAuthentication for implicit authentication of the services running in your cluster, where the nodes are setup with Managed Identities extension like described here.
Something link this:
When you use the Microsoft.Azure.Services.AppAuthentication, the Step 2 will be handled by the library and you won't have to add much changes to your key vault auth logic.
When you run your code on an Azure App Service or an Azure VM with a
managed identity enabled, the library automatically uses the managed
identity. No code changes are required.
The following docs describe other options you can use for KeyVault Authentication.
PS: I've done other KeyVault integrations using Client Secrets and Certificates and they are secure enough, With Certificates you can store it on the managed store or with the application, I would recommend MI only if is a requirement for your solution.

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.

ASP.NET Core appSettings.json security

I have an ASP.NET Core 2.0 WebAPI application that has Db ConnectionString in appSettings.json.
While in development it has this value:
"DefaultConnection":"Server=localhost;Database=Tyroll;Trusted_Connection=True;MultipleActiveResultSets=true"
and only when we publish it to production we change this with appropriate passwords, by using VS 2017 publish profile.
So SQL server passwords for are not stored on repository and no problem there.
The file appsettings.json is protected by IIS
The question I wonder is should this password be somehow 'hidden' even on IIS?
One reason being additional security, so that SQL credentials are not in plain text in case of breach here.
Another for some authorization scenario where IIS admin should not have directly access to SQL server.
I figure it could be encrypted and the app itself will have key for decrypting it. This would not be 100% secure since in the case of breach on IIS even this key could be reverse engineered from the app, but it would make it more difficult then when it's there in plain text.
So first question is should I be doing this at all?
And second if 1.Q is Yes, what would be the best / recommended way to do it?
Is there some built in tool for this in .NetCore2 or VS2017 or IIS, or some other tool?
Here are some related links:
reddit aspnet_core_appsettingsjson_security_question
stackoverflow is-appsettings-json-protected-by-iis
itprotoday passwords-webconfig
keeping-secrets-in-asp-net-core
I would suggest that you should user Active Directory Integrated security for accessing the database , the App Pool can run under the user account and that particular user account will only have the required access to the database . This safeguards the user credentials in case of an attack since the password is never exposed.
Solution I implemented is making custom encryption of Password in ConnectionString.
But since the App needs to the decrypt it, it is more an Obfuscation.
For encryption I have used AES (using System.Security.Cryptography) and the key is stored: half in connectionString itself and other half hardCoded in the Application.
In addition regex was used to extract Password from ConnectionString and then was replaced with decrypted string of it.

Signature issue SAML2p Kentor

I have my SAML2 enpoint in Azure and tried to integrate with Kentor Sample Mvc application. Everything went fine, Even I can see the SAMLRESPONSE with claims(attributes) in it. But I am getting a certificate error like "The signature verified correctly with the key contained in the signature, but that key is not trusted.' occurred in Kentor.AuthServices.dll" . Could anyone please help me on this?
This means that you've configured the wrong signing key with AuthServices. Since you're using Azure you should be aware that they roll over (i.e. change) keys regularly so you can't just configure the key. You have to configure AuthServices to load the Azure metadata automatically. Set the MetadataLocation property of the IdentityProvider to the metadata address of your Azure tenant.

How to provide private key access to the application pool identity?

I have come across this excellent blog explaining how to provide access to private keys and why its needed:
On www.microsoft.com we have a number of applications that use certs
to access other web services, the way we do is by installing the
certificate with the private key into the local machine store and
provide access to the application pool identity to the private key and
use the serial number or the thumbprint of the certificate in the
web.config of the application. One of the key challenge was to script
out the private key access to the application pool identity across the
server farm. (source: http://tinyurl.com/cbsmpqk)
At the time being my silverlight application can't access the database as it seems that it has no access to the installed certification (on Azure Cloud), as this is required to read the encrypted DB connectionString.
It says Failed to decrypt using provider 'CustomProvider' -> Keyset does not exist.
Following the blog above I was able to solve it by changing permissions for the installed certificate to additional read access for 'Authenticated Users' or even to 'Users'.
In both cases it works fine, but I don't understand the security implications. Does it mean now that anybody from Internet is able to read my certificate's thumbprint? Have I mistakenly opened a security hole?
Which username/Role should I rather have given the read access to the private keys of the certificate?
Many Thanks
Grant permissions to IIS AppPool\AppPoolName user. For example, IIS AppPool\DefaultAppPool.
From this answer: https://stackoverflow.com/a/2647003/991267
I don't think it means anyone can access your private key. If you set the 'authenticated user' or 'users' that means only the users in these groups would have the access permission. But if you set 'everyone' that means, everyone.

Resources