I’m trying to do a personal project and I want to use either Azure Key Vault or the appsettings that the Azure Web Apps provide by default. But I have only one concern. I guess if I want to use these, I still need to store some sensitive information, like TenantId, ClientId, ClientSecret, or Thumbprint if I use certificate.
If I use secrets.json then in development I’m fine, but if I publish it to the control version the application won’t work without these sensitive information, right? And in the appsettings.json I wouldn’t use them, because I don't want them to get pushed to the source control with the file.
What are your thoughts?
Thanks in advance!
Expected outcome:
I want to get the sensitive data from either Azure Key Vault or Azure Web App appsettings, but without using any sensitive data in appsettings.json.
(I think (Azure) TenantId, ClientId, ClientSecret, Thumbprint are sensitive enough, but please correct me if I'm wrong.)
You can use Azure Key Vault Secrets to store the following kind of values
a. SQL Conn String
b. Relay Conn String
c. Client ID (Service Principal)
d. Client Secret (Service Principal Pwd)
e. Any other sensitive values which are not supposed to be disclosed to developers.
Thank you #PeterBons #MattDouhan and #AlexeiLevenkov probably I need the Managed Identities :) Thank you guys for the quick help, I will mark the question resolved.
Related
Maybe there is an answer to my question already but I was not able to find it after a long time searching.
My use case is the following: I have one ASP.Net Core 3.1 web application. It uses MSSQL database to store some information (just FYI I don't store any users' secrets, but still the information is valuable for me). It also uses an email client to send emails. I need to store the connection string for the database and also the credentials for the email client. So far I was storing them in the appsettings.json file until I realized that they are stored in plain text and if somebody access them he/she will have access to my database and my email client.
Now I am looking for a way to more securely store them. After reading questions in SO I came to understanding that the suggest way for storing such information is by using the Azure Key Vault. I can use it and I started updating my application to work with it (I read that I can access it outside Azure). But I came to realize that I need to store somewhere the Vault URL, ClientID and ClientSecret values.
How can I store them. In one of the tutorials they had them in the appsettings.json file but they said that this is not a good approach for a production, which is understandable. Suggested option was to store them in environment variables. But here comes my problem - I am hosting on a shared server and I can't add any environment variables. So usage of environment variables is not an option for me.
In my case, when I can't add any environment variables what would be the best approach to store any production secrets like the database connection string? Is the Azure Key Vault still a valid and a good option? Should I consider keeping them in the appsetting.json and encrypting that file? Or maybe there is another better approach?
It is only me who is developing the app plus I don't store it in any public GitHub repo or anything.
PS: Here is a link to a tutorial I was looking at:Using Azure Key Vault From A Non-Azure App
Thanks.
EDIT:
Here is one tutorial which I find useful on how to Use Azure Key Vault With Certificate Outside of Azure
Two things:
1-You should store the secrets in Azure Key Vault. As you already noticed, it will provide an URL that will be used to retrieve the secret from Key Vault.
2-Only allowed services will be able to retrieve the secrets. What you need to do is create a manage identity to you web apps, then grant access to GET / LIST secrets from Key Vault to this Managed Identity.
here's a step by step:
https://learn.microsoft.com/en-us/azure/key-vault/general/tutorial-net-create-vault-azure-web-app
(Summarizing the discussion and resolution as Answer)
Storing secrets in Azure Keyvault is the recommended approach. However to get authorized access to KeyVault, you would need the credentials like ClientId and Secret or Certificate. So the question is where to store those secrets to access the KeyVault for the actual secrets! :). Now if you were in Azure host like for example Azure Web App or VM, I could straightaway recommend Managed Identity where you would not have to maintain the credentials in App, but since you mentioned it's a non-Azure host, I would suggest to go via Certificate authentication since Secret based auth would need you store the secret somewhere in config/environmental variable which is not a good idea. Also make sure that only your app has access to that certificate in the host.
As now you coordinated with your hosting vendor to configure certificate and things are working, I hope it helped. Thanks.
I'm new in ASP.Net core, I try to develop ASP.Net core MVC Web API. I need connect to my database. I no idea where I should put my connection string. I put it in appsettings.json file. But it will expose my database password when i deploy the API to the non Azure hosting. I try secret manager but it seem like just for development stage,not sure I understand right or not. I try to put in Environment variable but it not work when in my IIS hsoting.
May i know how I can secure my sensitive data when deploy to Non Azure hosting. Where should I put?
There is analog of Azure KeyVault it free and open source.You can store there your connection strings and others sensitive data.Also there is client library for .net
Your main choices are:
JSON (unencrypted)
Environment variable (unencrypted)
Azure Key Vault (encrypted)
As you correctly ascertained, JSON will be plain-text and is undesirable as a result, mostly because of source control. If you're working on a closed-source solution, this is less of an issue, though. Once deployed on the server, file permissions can keep the details from prying eyes. User secrets is just JSON. It's better in that it's kept out of your project (so it doesn't get committed to your source control), but it's still stored unencrypted, and yes, it's only for development.
Azure Key Vault is the only built-in option that allows encryption, and thus, is the most secure option. You can use Azure Key Vault whether or not your app is actually hosted in Azure. However, it's not free (though, it's also not very expensive).
Environment variables are what's most commonly used outside of Azure Key Vault. While unencrypted, they're stored on the server (outside your project) and are only visible to users with sufficient privileges on that server. If a malicious actor is able to gain access to an account with privileges to view the environment variables, it could be argued that you have far worse problems than exposing database credentials, already.
If the environment variables are not being seen by your app, there's two things to look at:
Ensure that you've added them as system variables and not user variables. User variables are only accessible by the user logged in while adding them (i.e. you), which is almost assuredly not the same user the web server is running as. Alternatively, you can log in add the web server user to add the variables as user variables. This is common when running under a service account. It adds a questionable degree of extra security as only that one account can see the values, not any admin level account (smaller attack surface).
If using IIS, you must edit the advanced settings of the App Pool, and enable "Load User Profile" from there.
I use "Manage Web secrets" to save db and any other crucial data secret from other developers and team mates
This will help you isolate, various platforms as well
you can read more at
https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows
I am developing .Net Core Web API 2.2 project and trying to protect it best I can. This application will be connected to SQL database plus it will be sending emails from the server, and therefore I would like to figure out what is the good way of protecting my sensitive data (such as connection string, database password or even email password for SMTP account).
I have read that it is bad practice storing your passwords in a plain text in your file somewhere and one of the best practices is to use some Microsoft Azure functionality (where you provide some key and it returns you the actual password) that I have not yet used. Furthermore I do not have any subscription with Azure, and for the time being I would like not to go that direction.
Another method proposed by some of you guys was to store all the password to Environmental Variables and simply reference it in the application. I am currently exploring this option, as my app will be hosted on a 'virtual windows server' where I do not have direct access to, and thus it's difficult (without direct access) to get there and set up environmental variables (not even sure if that would be possible).
Finally, so far the best option (in case it will not be possible to use the variables mentioned above), was to actually store connections and passwords directly to appsettings.json file, but to hash them and decrypt on run-time. This option for me is surely feasible; however I wanted to ask (even though this might be quite subjective) you guys, whether this is a correct approach or there is something I have missed that could help me better to protect my application from external threats.
Any suggestions or advices would be more than appreciated as I do not really know now how to proceed.
P.S. I am using VSTS repository to store all the application code, which might be probably (I am guessing) the reason why people suggest to at least hash your passwords when storing them in appsettings.json
The appsettings.json file should never be used for secrets simply because it's committed to source control. That alone makes it a bad choice. However, there is also no capability to encrypt anything in appsettings.json. You could, I suppose, encrypt your secrets via some other means and merely place the ciphertext in appsettings.json manually after the fact, but then you would need some facility to decrypt the secret later, when then means exposing your means of encryption (i.e. your private key), which kind of defeats the entire point. Long and short, don't use appsettings.json.
Environment variables are a compromise solution. Since you manually set them on the server (not in your source control) and they can be made to only be accessible to certain users (restricted access), you get a modicum of security. However, they are also stored plaintext, which means if someone is able access the server to view them, all security is out the window. Environment variables can also be set as part of your CI\D pipeline in DevOps (formerly VSTS), so direct access to the server is not necessarily a prerequisite as long as the service account doing the deploy has the necessary access.
Azure Key Vault is the recommended approach because it's the only built-in config provider that supports encryption, meaning your secrets are encrypted at rest and pretty much secure end-to-end. However, there's nothing uniquely special about Azure Key Vault other than its ready availability. You can conceivably use any type of service that lets store secrets securely; you may just have to write your own config provider to target it.
I've been playing with PowerShell this week creating a new Azure environment for our deployment, the final part of this calls for a WebJob written in C# to accept a message from a queue and create a new database and create the structure as required.
I was wondering if anyone here has done this before, I have found the azure management libraries for .NET which have examples of database creation but I'm stuck on the authorisation as this will be done from a back end process?
Is there anyway I can create a trust in my Azure environment to allow my WebJob to connect Azure (although the app is running in the same subscription) and create a new database?
At this time I don't really have any code more like ideas which is why I'm asking for help :)
I am assuming I would use something like this to authenticate?
var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(
"clientid",
"clientsecret",
"tenantid",
AzureEnvironment.AzureGlobalCloud);
// Connect to Azure
var azure = Azure.Authenticate(credentials).WithDefaultSubscription();
I assume I may need to do something in Azure itself to trust the WebJob to have the access to create a new Azure database but this is the part I'm not sure about.
From PowerShell I've done the authentication by letting PS bring up the Microsoft Live Login Screen but this is not practical for a WebJob with no UI.
Hope this makes sense, and someone can shed some light on it for me?
You are on the right track.
You will have to create a service principal for the WebJob, which is essentially credentials for an app. You will get a client id and secret for it (which are the app's username and password), which it can use to authenticate against Azure Active Directory, and get an access token to call into APIs (such as Azure's management APIs).
You can see here how to create the app in Azure AD (which also creates the service principal): https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal#create-an-azure-active-directory-application
Then you can assign a role for the service principal on any resource/resource group/subscription. Since you need it to be able to create resources, it should be a Contributor on a resource group at least. If you also need to create a resource group for
So:
Create the app as in the documentation
Add a key (client secret) to the app as in the documentation
Copy the client id and secret + the tenant id as you will need them later when using the APIs
Assign a role/roles for the service principal via the Portal
You can now write the program which uses the credentials you got (this library is pretty nice: https://learn.microsoft.com/en-us/dotnet/azure/dotnet-sdk-azure-concepts?view=azure-dotnet)
Short note on storing secrets:
You should be careful with the client secret, it is essentially a password.
At minimum, you should store it in the App Settings of the Web App, not in code. An even better way is to use Azure Key Vault together with Azure AD Managed Service Identity: https://joonasw.net/view/azure-ad-managed-service-identity.
I have a working script via https://learn.microsoft.com/en-us/sql/relational-databases/security/encryption/configure-always-encrypted-keys-using-powershell (KeyVault + SQL Azure setup). Now I have plain Azure PS (KeyVault creation), reflected assemblies (SMO, SqlClient, ConnectionInfo) and the SqlAzure module (column encryption).
Long story short - could I do all that in C#? (I have an existing workflow using the fluent management libraries, and shelling out to PS is something I'd like to avoid if possible).
You may be able to do that. One idea that comes to mind is to generate separate AAD applications (Id, Secret pairs, See "Generate Application ID and Secret" section of this article) for each role with appropriate permissions and take the take ID, secret as an input from the user. Also, the article describes how to integrate Azure Key vault with C# application and use it for Always Encrypted. If you have additional questions, please share them in the comment section so I can help you answer them.