Using a certificate to grant an application access to Azure Key Vault - azure

I have a web API hosted on Windows server via IIS. I'm using Azure Key Vault to hide secrets. In order to give the application access to the vault, I am using a certificate installed on the server, which is also registered with the application in Azure.
The certs thumbprint, the tenant ID, and the application ID are all exposed in the configuration file of the web API. The apps registration is granted access via policy in the key vault.
The issue is that the integration assistant in Azure is alerting me that I should not have a certificate set up inside the registration, but with no explanation as to why (the documentation is greyed out for alert).
Can this alert be safely ignored? Or is there a better way to grant my application vault access?
Edit - snip of integration assistant:

Can this alert be safely ignored?
In your particular scenario, I would say yes. You can safely ignore this message.
Essentially you need a user to access the key vault. Considering your application is running locally, you would use the Service Principal (created as part of the app registration) as a user to access the key vault.
Or is there a better way to grant my application vault access?
In your particular scenario (when your application is running locally), AFAIK no.
If your application were running in Azure, you could have used Managed Identity. It could be either System-assigned Managed Identity or User-assigned Managed Identity. With managed identity, you need not require a secret/certificate based authentication.
I am not sure if your API is protected by Azure AD (i.e. a user must be authenticated/authorized before using the API), but if it does then one alternative would be to grant users of your API access to Key Vault. Requests to Key Vault will then be sent in context of that user. This however will increase the management complexity considerably as you have to manage access control for all your API users.

Related

How to securely give external application access to key vault in Azure

I have a vendor application, possibly a SAAS application that want to access my key Vault in my Azure tenant, which is behind a firewall. Can anyone the suggest the best way to give the vendor access to my key vault? please drop a comment if you have done this before.
There are 2 ways, from which you can give the External vendor application access to your Azure key vault.
You can create a new service principal/app registration in your Azure AD tenant which will model the vendor application and provide that service principal access to key vault secrets and certificates, Via adding that service principal to the access policy with RBAC role. And then giving your vendor the Application client ID, Application secret, Tenant ID to use this app in their SAAS vendor app code for authentication to Key vault in your tenant. If the SAAS Vendor application already resides in your tenant, This method will work too.
I created a key vault resource on Azure :-
I created one single Tenant App to use for this tenant and then added that app to the access policy of Azure key vault.
Select your key vault from Azure Portal> Left pane> Access Policies> Add> Select the secret, key and certificate permissions as required > In Principal select your Single Tenant App> Next> Create
Singletenantapp is added to access policies with below permissions on Key vault:-
Now, You can provide this singletenantkeyvault application’s > tenant Id, application client ID, secret to the SAAS vendor application code as this Singletenantkeyvault application will model your real world SAAS vendor application.
Example-
{
"DNSNameKeyVault": "https://siliconkeyvault123.vault.azure.net/",
"AADAppRegistrationAppId": "7dad56d0-29d7-4d14-8dbe-4b9787895942",
"AADAppRegistrationAppSecret": "<app-secret>",
"SomeSecret": "DEV_VALUE"
}
Similar settings should be added to your SAAS vendor’s application’s appsettings.json folder depending on the framework that the SAAS vendor’s app runs on.
Note- Access policies can only be added to the Users and Applications in your directory only, you cannot add access policies to the external application that resides in other tenant/directory. You can either create a new application in your tenant or enable Multi-tenant application.
You can create a multi-tenant app shared between your External SAAS vendor’s tenant and your tenant, And assign the Key vault access policy to that Multi-tenant App. In this way you can use the existing SAAS vendor app in their tenant with your tenant to only give least privileged access to control Key vault.
I created a multi-tenant asp.net core app in my Default Directory tenant: -
MultiTenantAuth App is created successfully in our Azure AD Default Directory tenant
You can also create a multi-tenant app within Azure AD portal like below:-
Now, either you can authenticate with your SAS vendor application with your tenant and access key vault via running the code from VS studio or you can call this endpoint and replace the SAS vendor’s tenant ID with yours to get the SAAS vendor application from their tenant to your tenant and then provide the required access:-
In this example- Your MultiTenantDemo or MultiTenantAuth app is your SAAS vendor’s tenant Application which will be added in your or other tenant by either running the code or by calling the below endpoint.
In this example- I created MultiTenantDemo, MultiTenantAuth applications in my Default Directory and now I am adding them in my other directory SiliconSid.
https://login.microsoftonline.com/tenantid/adminconsent?client_id=clientid&state=12345&redirect_uri=http://localhost/myapp/permissions
I logged in with my another tenant’s admin user and accepted the consent for the app from my default directory to the new directory
After I called this endpoint, the Application is added in my another directory SILICONSID:-
Now, I’ll add this application in the Access policy of my key vault :-
Is inviting the user from your SAAS vendor’s tenant to your tenant and giving the user access to your key vault access policy if your saas vendor real world application uses username and password as authentication and not Service principal.
You can invite your SAAS vendor’s user like below:-
Invite the user and only provide the user access to your key vault:-
You can invite the SAAS vendor user via Email
An invitation link will be sent to the user’s email once the user accepts the invitation, He is redirected to your Azure Portal and is added in your Azure AD.
The SAAS vendor user can log in to Azure Portal and select your directory> and access the Key vault given you added that user to your access policy like below:-
You can again apply the policy of least privileged here and provide user only the access to the key vault and nothing else. You also need to provide the invited user access to your Subscription’s Key vault resource group with key vault role to only read key vault. This can be used if your SAAS vendor real world application uses Username and password as authentication in their Code and not service principal application.
The best way here is to either create a new application in your tenant or to create a multi-tenant application. Point 3) is not recommended and is not a best security practice.
Reference:
Azure Key Vault considerations for multitenancy - Azure Architecture Center | Microsoft Learn

How to use aad authentication or managed identity to access resources with torus system in azure?

We previously used keyvault and connectionstring to access resources in azure. However it will generate many parameters needed. We want to simplify the process.
We wanted to use aad authentication.
Firstly, we tried certificate-based aad authentication https://learn.microsoft.com/en-us/azure/cosmos-db/sql/certificate-based-authentication first, it works. But the thing is, in keyvault the certificates are set auto-rotation, but in aad app, we can only manually upload new certificate each time (I know there are methods like VM extension or extra software can do auto renewal, but it's complicated. We just want change configs in azure portal and change service code to access.) In this situation, when certificates becomes more and more, it's not suitable to manually renew each cert in each aad app. I notice in some places it says setting tls/ssl settings which makes auto-renewal, but currently in azure portal, it just can manually upload certificates. Only in function app can do tls/ssl settings.
Secondly, then we notice another one as managed identity. It simply says azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/"); to get token. But the thing is, current login tenantid is microsoft.onmicrosoft.com, but the resources and the subscriptions are all in prdtrs01.onmicrosoft.com through torus account.
Even I try with string accessToken = azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/", prdtrs01tenantid) still does not work, saying AADSTS50020: User account '{EmailHidden}' from identity provider '...' does not exist in tenant 'PRDTRS01' and cannot access the application '...'. It seems just cannot get token from prdtrs01 tenantid.
Also, I tried to replace the aad app used in first method with the function app used in second method to do certificate-based authentication. However the function app does not have a clientid, just principalId and user managed identity's clientid. Both ids fail with ClientAssertionCertificate credential = new ClientAssertionCertificate(clientId, cert); in certificate-based authentication. It finally says "Client assertion contains an invalid signature. [Reason - The key was not found., Thumbprint of key used by client".
In all, I described several ways we tried, but all failed. Can anyone help?
Thanks
AADSTS50020: User account '{EmailHidden}' from identity provider
'...' does not exist in tenant 'PRDTRS01' and cannot access the
application
As per this first error , it means that the account you are using to access the application is not a part of the tenant that the application is hosted on.
Make the application as a Multi-Tenant Application :
You can convert the application to accept users from multiple tenants. In this way you can give access to users who are not in your tenant without having to add them to the tenant where the application is in.
Maybe account type is set to Accounts in this organizational directory only.
You may have to change it to Accounts in any organizational directory.
Go to Azure portal -> Azure Active Directory -> Manage -> App Registrations --> your app name -> Supported Account Types
(or)
Add the user to the tenant as guest :
You may need to add the user to the tenant that the application is hosted in. You can follow this document to add the user with your domain as a Guest User to the tenant. And grant access to the application for the said user.
However, if your authentication call is for specific tenant i.e., https://login.microsoftonline.com/yourtenantname or_id, users from other organizations won't be able to access the application and are required to be added as guests in the tenant specified in the request.
In your case, try to authenticate request like https://login.microsoftonline.com/organizations or https://login.microsoftonline.com/common

secrets vaults: how to encrypt clientId and clientSecret in a web app?

People say not to store API Keys and passwords config files and instead to use a Secrets vault. eg. AWS or Azure.
But to access these you need a clientId and clientSecret. These need to be stored somewhere on the app. eg app.config. So I really don't understand what problem this solves if the hacker can use the clientId and clientSecret in the app the get the passwords or api keys anyway?
it seems even worse than the original problem storing one api key, since if they get access to the secrets manager they will have ALL THE KEYS and ALL the passwords.
AWS offers few different services to store your secrets. Let's say if you have a database password in an application configuration file, you can use either AWS Secret manager or AWS Parameter store to store them as secret.
To retrieve these values securely, you do not have to store another secret stored in your application. You can use a mechanism called role-based access in AWS.
If you running your application on an ec2 instance, you can configure an AWS role/profile and assign it to the ec2 instance which is linking the secret manager and the ec2 machine securely and your application has connectivity to decrypt the secret and use it inside the application.
If you are using Azure, the answer is to use Managed Identities.
The way it works is that you assign an identity to the resources (VMs, WebApps etc.) that need access to Key Vault. That way the resource becomes like a user in your Azure AD (much like a Service Principal or any other user). Then you can make use of Key Vault Access Policies to assign appropriate access to keys and secrets in your Key Vault to these Managed Identities. Doing this would not require you to specify a Client Id/Client Secret to access the Key Vault.
While the Managed Identity is something you assign to a resource, it could become cumbersome if you have many resources. That's where User Assigned Managed Identity comes into picture. A User Assigned Managed Identity is a resource in your Azure Subscription. The process is very much similar: you create such identity and then assign appropriate access to this identity on your Key Vault resources.
Now wherever you need to access Key Vault in your applications, you will specify the id of this identity. The application using appropriate SDK will get an access token on behalf of this identity and connect to Key Vault using that access token.
You can learn more about these identities here: https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview.
But to access these you need a clientId and clientSecret. These need to be stored somewhere on the app. eg app.config
You can use runtime permissions to access the secrets and parameters. In Azure it is called Managed Identities, in AWS there are service roles. I am more familiar with AWS, so I will use its terminology, but every larger cloud provider has similar approach with different names.
Basically you can assign the compute resource where your code runs (EC2/VM server, Lambda function, ECS container,...) a role - you can consider it as set of permissions. Using AWS API you can access the secrets or parameters from the code without storing any client credentials.
if they get access to the secrets manager they will have ALL THE KEYS and ALL the passwords.
That's why we all need to use principle of the least privileges, the defined runtime identity should have only permissions it really needs.

Azure Key Vault secret to store app users secrets

In my application I have to store very sensitive data of its users, such as various password to other 3rd part services (user fill a form where he provides us login and password to 3rd part service)
The goal of the application is to setup other complex system using powershell scripts generated from over 100 inputs. There is a requirement to save user work as draft, and that is why I need to encrypt sensitive fields somehow.
I read a lot about Azure Key Vault and whenever I read about secrets it seems they are described to hold app settings rather then users secrets, so i am not sure if this is right to place those data.
Is Azure Key Vault secrets suitable for that job?
Moreover i am able to peek those value in azure portal as in plain text, and I want to avoid that. I suppose that I could encrypt them first and store already encrypted values, but this may be over engineering.
It's not clear what you are describing as user secrets. If it's user credentials, then you need to federate login to an Identity Provider like Azure AD or Azure AD B2C. Key Vault is NOT an identity provider, but a secret store. If it's application secrets (think connection strings) then you should look at Key Vault (with Managed Service Identity).
Conversely, Application Settings (in App Service) are exposed in the Portal but are encrypted at rest. So if you're careful about who can access what within your subscription namespace, you should be just fine.

A more secure way to use key vault

Usually when you use key vault to encrypt and decrypt data you have to keep your AD registered app's (that has the authorization to access key vault) ClientID and ClientSecret in plain text somewhere. This seems like a security problem if someone steals the the ClientID and Secret anyone can claim they are the registered app.
Is there or can there be a more secure approach?
You can use a certificate to authenticate instead of a secret.
There are three things you need to do for this approach:
Create a certificate to use.
When creating the Active Directory application that you will use to access the Key Vault, you need to pass in the certificate you created in step 1. I don't think you can do this through the portal at the minute, so you'll need to use the New-AzureRMADApplication PowerShell command.
Use that certificate when authenticating to Key Vault. You'll need to use an overload of the AuthenticationContext.AcquireTokenAsync() method that receives a ClientAssertionCertificate to do that. You can create a ClientAssertionCertificate by simply passing the client id and the X509Certificate2.
From this blog post you can get some some code for the first two steps.
In addition to using certificate-based with KeyVault, Azure Managed Service Identity also introduces a new way to make an Azure service become a service principal without any client app registration and client secret. Currently it is only available in preview stage for some services: Azure VM, Azure App Service, Azure Function, Azure Event Hub & Azure Service Bus. More information can be found here https://learn.microsoft.com/en-us/azure/active-directory/msi-overview
[Update] When ever you need to retrieve something from KeyVault, with Azure MSI you don't need a client secret. Only use AzureServiceTokenProvider() method to retrieve access token
In real-world deployment with automation (for example via Ansible), you can use an external certificate to store sensitive variables in Ansibe Vault and generate a 256bit chain to secure such an info. During the automation deployment, the cert is decrypted to access to these variables and perform further deployment. This way adds more encryption layer to the whole Azure deployment.

Resources