Storing Azure Vault Client ID and Client Secret - .net-core

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.

Related

Risks of developer signing credentials

According to the Identityserver4 documentation the AddDeveloperSigningCredential is, as the name implies, for development purposes only. I have found several articles that describe the process of switching to other signing certificates that are more geared towards production environments. My question is why is the switch necessary? Are the generated developer signing credentials insecure in some way, and if so what is the attack vector that can be exploited? What if I am running my identity server through an nginx reverse proxy and using an aws cloud signing credential through a load balancer? Does that adequately resolve the exposed attack vector? In short what risks are there to using developer signing credentials in production?
The generated RSA key (2k) is from a security point of view totally fine - you won't get "bad crypto" compared to a "production key".
The main problem with the dev signing key is that it is loaded from the local hard-disk - and especially (by default) from the application directory.
You should have a more secure storage location for keys (e.g. the Windows certificate store or some storage service) so that in case an attacker can read files from the app server hard disk cannot easily recover the private key.

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.

How to manage (non-SSL) certificate in an Azure App Services?

We want to switch our ASP.NET MVC application from Azure Cloud Service to Azure App Service (web app). The application is currently using WIF as its identity framework, and as it is running in a farm configuration, we configured a custom SessionSecurityTokenHandler which encrypts the session cookie using a certificate (thus the cookie can be decrypted by all instances of the web farm).
We could provision this certificate in the Cloud Service scenario using the csdef/cscfg files and the built-in Azure certificate store associated with the Cloud Service, but there is no such thing with Azure App Services (unless I missed something).
Is there any way to configure a certificate in the App Service? Should we fall back to another mechanism to encrypt the session cookie, such as a shared machine key? The machine key is not an ideal solution as it forces us to leave some configuration out of source control to avoid leaking the key.
Using the Azure portal (https://portal.azure.com), open the web app blade for your web app and click on the Settings button in the toolbar.
In the Settings blade, click on Custom domains and SSL. In the Custom domains and SSL blade click on the Upload Certificate button in the toolbar. This will open a blade where you can upload the certificate.
In the web app settings blade, you will need to add an app settings using the key WEBSITE_LOAD_CERTIFICATES. You can set the value to * to load all certificates or if you want to specify a specific certificate you could do that.
From there, you can use the certificate like you would in your cloud service version of the application. Some additional information on this and how to use the certificate in code is available here if you need it.
Finally, to Michael B's point in the comments, using Azure Key Vault would be another approach you could take and would provide some additional security.

Apigee key management in Java

For our portal development, we have decided to use Apigee to expose the web service to the portal. For which currently I am storing the API Key and Api URL in the properties file of the project. Can anyone help with some pointers on how else can I save the API key apart from the properties file.
Any pointers will be helpful in this case.
Regards
Aswathy
Typically the API key will be persisted by the the API consumer - usually an App of some kind. In case of Mobile Apps, each of them have an API Key or Client ID that is saved inside the app usually in some kind of secure data store. For other kinds of API consumers such as web apps the API Key may be persisted within a secure vault or an database that has some encryption features.
I assume your web portal app resides on a secure machine inside your enterprise and that this machine is access restricted. If this is the case bare minimum security is taken care of
However, If the key is a high privilege key and you can access APIs with key alone(ie without a secret), it is not advisable to keep it in plain text.
You can
1. Encrypt and store it in the config file and decrypt at runtime
2. Encrypt and store in Database or other secure storage you use for storing credentials.

Using DPAPI / ProtectedData in a web farm environment with the User Store

I was wondering if anyone had successfully used DPAPI with a user store in a web farm enviroment?
Because our application is a recently converted from 1.1 to 2.0 ASP.NET app, we're using a custom wrapper which directly calls the CryptUnprotect methods. But this should be the same as the ProtectedData method available in the 2.0 framework.
Because we are operating in a web farm environment, we can't guarantee that the machine that did the encryption is going to be the one decrypting it. (Also because machine failures shouldn't destroy our encrypted data).
So what we have is a serviced component that runs in a service under a particular user account on each one of our web boxes. This user is a set up to have a roaming profile, as per the recomendation.
The problem we have is that info encrypted on one machine can not be decrypted on another, this fails with the win32 error:
'Key not valid for use in specified state'.
I suspect that this is because I've made a mistake by having the encryption service running as the user on multiple machines, hence keeping the user logged in on more than one machine at the same time.
If this is the problem, how are other using DPAPI with the User Store in a web farm environment?
In a web farm environment, rather than using DPAPI to encrypt/decrypt your data directly, you would instead use it to encrypt the key that you later use to decrypt your protected data.
You would "install" the key onto each server as part of the deployment process. The installation script would need to run under the AppPool's identity, and could store the encrypted key either in an app.config file or in the registry.
The encrypted data itself could be stored in a central repository / database, so that it can be accessed by all servers in the farm. To decrypt the data, the web app would retrieve the encrypted key from where it was installed, use DPAPI to decrypt it, then use the result to decrypt data that comes from the central repository.
The downside is that the cleartext key might exist on the local disk for a short time during the initial install process, where it might be exposed to operations staff. You could add an extra layer of encryption, such as with the web.config machineKey, if that's a concern.
The Microsoft poster is wrong.
http://support.microsoft.com/default.aspx?scid=kb;en-us;309408#6
"For DPAPI to work correctly when it uses roaming profiles, the domain user must only be logged on to a single computer in the domain. If the user wants to log on to a different computer that is in the domain, the user must log off the first computer before the user logs on to the second computer. If the user is logged on to multiple computers at the same time, it is likely that DPAPI will not be able to decrypt existing encrypted data correctly."
It appears that DPAPI will not work in a farm setting. I think this is a rather large oversight on Microsoft's part and makes DPAPI almost useless for most enterprise applications.
I just saw this. There is a way you can make this work, and that is to make sure the machines in the farm are in a domain, and use a domain account to encrypt and decrypt the data (ie; run the application under the domain account)
You cannot use DPAPI in the manner you want with local accounts because the key material is not exchanged between servers.
hope that helps!
Twelve years later . . . you can try using CNG DPAPI, which was meant to work in cloud environments that may or may not be load-balanced. From that link (in case it gets taken down):
Microsoft introduced the data protection application programming
interface (DPAPI) in Windows 2000. The API consists of two functions,
CryptProtectData and CryptUnprotectData. DPAPI is part of CryptoAPI
and was intended for developers who knew very little about using
cryptography. The two functions could be used to encrypt and decrypt
static data on a single computer.
Cloud computing, however, often requires that content encrypted on one
computer be decrypted on another. Therefore, beginning with Windows 8,
Microsoft extended the idea of using a relatively straightforward API
to encompass cloud scenarios. This new API, called DPAPI-NG, enables
you to securely share secrets (keys, passwords, key material) and
messages by protecting them to a set of principals that can be used to
unprotect them on different computers after proper authentication and
authorization.
In .NET Core this looks like
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.ProtectKeysWithDpapiNG();
}

Resources