Configure Always Encrypted for SQL Azure with KeyVault using C#/.NET - c#

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.

Related

How can I store production secrets like connection string in ASP.Net Core 3.1 application, hosted on a shared server

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.

ASP.Net core how to secure connection string sensitive data in non Azure hosting

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

Store secret key securely in .NET Standard cross-platform app

I'm working on a C# PowerShell module, which is going to be a simple wrapper around some service REST API. I'd like to target PowerShell Standard / .NET Standard and make module available across all supported platforms.
For this app authentication requires API token, issued on a service website by the user. Entering key every time you open a session would be extremely inconvenient and therefore I need some way to securely store the API key in a user profile.
The problem is - I cannot find an easy way to encrypt data that has transparent cross-platform support. Initially, I wanted to use SecureString, but it is (a) deprecated and (b) doesn't seem to have good support on Linux. In a perfect world I'd like to have some mechanism similar to Windows encryption - user certificate encrypts API key and I put result in a text file in a user folder.
This is not a financial or mission-critical application, top-notch security is not required, but still keening plain text secrets in my home folder makes me nervous. Yes, I'm talking to you, AWS SDK authors :)
My first thought was: "just save secret key to ENV variables..."
But if I understood OP's question correctly, it is required to restrict unauthorized reading of this secret even on OP's machine.
One option I could see is just create a folder (or maybe file) and give it the access permissions only for one particular user. Ultimately one can create new user account which will be used to run the code in powershell and give this new user exclusive permissions to read secret file. This will prevent some 3rd party programs running from OP's account to read secret file.

Net Core Web API 2.2 Protecting sensitive data

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.

Obtaining sensitive data from the user and storing it without hashing so that it can be restored

I'd like to ask for some advice on the app security when it comes to getting the password from the user and storing it.
I'm developing a tool using .NET Core (console project) and Selenium WebDriver to automate a process on a website, which requires authentication, and my concerns are following:
1. Getting the password from the user (using console) and securely handle it
2. Storing the password in a secure manner
Regarding the first point:
I've found an answer on
SO pointing out that
using
SecureString
doesn't fully prevent sensitive data to be read as at some point it
has to be converted to/from normal string. I have come across the
solution
for getting user input from console using SecureStrings, but
according to what's written
here
SecureStringToBSTR has to be used to handle the sensitive data in a
secure way. However, SecureStringToBSTR is not included in .NET
Core, because it's
available only for Windows thus I'm stuck.
As for the second point:
I cannot hash the password as it has to be restored. At first I
wanted to use platform specific solutions and check the current
platform in the app, but after a research I found out that there's API only for DPAPI for Windows, there's no API for KeyChain in MacOS (there's some workaround) and Linux doesn't have a unified way of storing sensitive data at all. The only solution I can think of is to force the user to generate public/private keys (using for example RSA which is available on all platforms, encrypt the password using public key and require private key to retrieve the password. Then I would store the encrypted password either in appsettings.json or as an Environmental variable as desribed here. Unfortunately Azure Key Vault is not free
I am aware that there are many questions similar to this, but:
I couldn't find any regarding storing passwords, most sources focus on hashing them, however, it doesn't apply to described use case
Virtually all are focused on ASP.NET Core MVC
Thanks in advance for the hints.

Categories