Dynamically accessing certificates uploaded in Azure portal from cloud service - azure

I want to use certificates (uploaded, via the portal, to the cloud service deployment) in my cloud service webrole.
I would expect that - after uploading the certificates - they would be applied to my running web roles and I can then find the certificates via their thumb print.
I upload the certificate via the portal by going to my cloud service, selecting "Certificates" and then uploading the .pfx and providing the password.
This is the code I am using to try to get certificates:
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 certificate = null;
foreach (X509Certificate2 cert in store.Certificates)
{
string certHash = cert.Thumbprint;
if (certHash.Equals(binding.SslThumbprint, StringComparison.OrdinalIgnoreCase))
{
certificate = cert;
break;
}
}
This works if I register the certificates in the .csdef file, but I need to be able to load the certificates dynamically. Changes to the .csdef file require deploying a new package - which is not an option.
There is a similar feature in azure websites that you can add a WEBSITE_LOAD_CERTIFICATES setting with a wildcard value to your app setting and then find them by thumbprint in the code. Basically I am looking for a similar feature in cloud services.

There is no ability to dynamically load certs uploaded to the Azure portal into a Cloud Role without specifying them first in the CSDEF/CSCFG files.
You can, however, upload your certs to some external storage (ie: Blob storage, SQL Azure db, etc or as Poul mentioned Key Vault) and load them from there.
HTH

Related

Use Azure keyvault secrets offline when developing .NET core Azure functions

When I develop for Azure I usually start copying in some keyvault client code so only keyvault urls will be in my settings file, no secrets can ever end up my git repositories.
After starting to make Azure functions I realized that it was not possible to do this for the trigger connection string for e.g. service bus or blob storage.
The recommended approach seems to connect the app to keyvault directly in Azure when deployed, and just manage secrets locally in Secret Manager, like suggested in
this article
I am not developing alone, so while I am not adverse to using a tool like Secret Manager, I need to still have my offline secrets connected to the Azure keyvault! If others change anything.
Question: How do I manage secrets offline in a way that is synchronized with Azure keyvault?
it was not possible to do this for the trigger connection string for e.g. service bus or blob storage.
In short, it's possible.
Here are steps you could follow and refer to the detailed article.
1.Add a System Assigned Managed Identity to the Azure Function.
2.Go to the Access Control section of your Key Vault and click on Add a role assignment blade.
3.Go to your Key Vault and click on Access Policies and then click on Add service principal with secret GET permission.
4.When you use ServiceBusTrigger, you set ServiceBusConnectionString in Function ->Configuration ->Application settings.
public static void Run([ServiceBusTrigger(_topicName, _subscriptionName, Connection = "ServiceBusConnectionString")] string mySbMsg, ILogger log)
{ ....
}
5.Now you change the value of ServiceBusConnectionString to the Azure Key Vault reference with #Microsoft.KeyVault(SecretUri=Secret URI with version). Then you could run your function successfully with Key Vault.

Signing binaries while deploying automatically to Azure App Service from github

I wanted to sign my binaries while deploying to Azure App Service through github (using Kudu underneath). I understand I can run a custom script for building the project. Maybe I could use this method to sign the binaries during the build process and deploy the signed bits? I suppose I can place my certificate in Azure Key Vault. How can I access this without checking in any secrets into github?
Anybody have experience with this?
You're on the right track here. A custom deployment script should do it:
http://blog.amitapple.com/post/38417491924/azurewebsitecustomdeploymentpart1
https://github.com/projectkudu/kudu/wiki/Custom-Deployment-Script
In Kudu you won't have Azure PowerShell installed, so you'll have to pull your certificate from Key Vault over REST.
UPDATE: Azure Functions do have the Azure RM cmdlets installed. You could write a Function App in PowerShell that pulls the cert from Key Vault. Use a Service Principal to Login-AzureRmAccount unattended.
The secrets needed to accomplish that should be kept in Application Settings. They are exposed to you in Kudu as Environment Variables: https://azure.microsoft.com/en-gb/documentation/articles/web-sites-configure/
App settings
This section contains name/value pairs that you web app will load on start up.
For .NET apps, these settings are injected into your .NET configuration AppSettings at runtime, overriding existing settings.
PHP, Python, Java and Node applications can access these settings as environment variables at runtime. For each app setting, two environment variables are created; one with the name specified by the app setting entry, and another with a prefix of APPSETTING_. Both contain the same value.
Alternatively, you could pull the certificate from App Service store (the "My" store). Here's how:
From https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/:
Adding an app setting named WEBSITE_LOAD_CERTIFICATES with its value set to the thumbprint of the certificate will make it accessible to your web application. You can have multiple comma-separated thumbprint values or can set this value to * in which case all your certificates will be loaded to your web applications personal certificate store.
using System;
using System.Security.Cryptography.X509Certificates;
namespace UseCertificateInAzureWebsiteApp
{
class Program
{
static void Main(string[] args)
{
X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
// Replace below with your cert's thumbprint
“E661583E8FABEF4C0BEF694CBC41C28FB81CD870”,
false);
// Get the first cert with the thumbprint
if (certCollection.Count > 0)
{
X509Certificate2 cert = certCollection[0];
// Use certificate
Console.WriteLine(cert.FriendlyName);
}
certStore.Close();
}
}
}
No certificate validation is being done for you. You need to implement that yourself, by comparing to values stored in App Settings or Key Vault.

Upload certificate to azure with exportable flag

I want to make Azure WebApp instance (with .Net WebAPI2) to use Google service account certificate.
Steps I went through:
Create and download .pfx from Google developers console.
Upload .pfx to Azure WebApp -> Custom domains and SSL.
Introduce new variable in AppSettings. Key: WEBSITE_LOAD_CERTIFICATES Value:
(or thumbprint)
After completing these steps I am getting:
CryptographicException. Key not valid for use in specified state.
One of the reasons I would think of is that it needs an exportable private key, but there are no options (or at least I have not found) to change while uploading it.
I have tested the certificate it works locally.
How to solve this?

Certificate not found on Azure Web App

I deployed a web application as a Web App on Azure App Service.
I uploaded some certificates to the Azure Portal, since the Web App runs over SSL, and we use another certificate to perform some decryption.
For the latter case I have a method (which works fine locally) to find a certificate:
public static X509Certificate2 FindCertificate(KnownCertificate certificate)
{
return FindCertificate(StoreName.My, StoreLocation.CurrentUser, X509FindType.FindByThumbprint, certificate.Thumbprint);
}
But I get an error that the certificate with thumbprint XYZ is not found. Although, on the Azure Portal it is present. (I had uploaded and imported it)
I am using StoreLocation.CurrentUser as suggested in THIS POST but it still does not work. Am I using the wrong store or what else am I missing?
EDIT: I have managed to remotetly debug my WebApp and with the ImmediateWindow feature of VisualStudio I have executed this code
new X509Store(StoreName.CertificateAuthority, StoreLocation.CurrentUser).Certificates.Find(findType, findValue, false).Count;
testing all possible combinations of StoreNames and StoreLocations but to no avail.
Is it possible like stated here that for using certificate with purposes other than https traffic you would need a Cloud Service and that (I suppose that) App Services do not support it?
You need to add WEBSITE_LOAD_CERTIFICATES to your web app App Settings. Set the value to either ' * ' or to the thumbprint of your certificate you want loaded into the web app environment. My personal preference is to set this value to ' * ', which means, load all certificates that have been uploaded.
After you apply this change you should be able to load your certificate from within your web app code.
More information on how to use certificates is available here. The article is a bit dated (in today's standards) but still relevant.

Cannot add a certificate in local Azure Web role VM

I have some difficulties in managing Azure certificates from my code.
Indeed I'm trying to use Azure REST Services API (e.g. creating HTTP requests) in order to know my services state from my Azure web site.
It works well in local debugging, but my web role seams to have some limitation with the certificates manager. Bellow is what I do:
// this method stores a certificate from the resources
// to the local certificates manager
private X509Certificate2 StoreCertificate(Certificates certName)
{
X509Certificate2 newCert = null;
// get certificate from resources
newCert = this.GetCertificateFromResources(certName);
// store it into the local certificate manager
if (newCert != null)
{
var store = new X509Store(
StoreName.TrustedPeople,
StoreLocation.LocalMachine
);
store.Open(OpenFlags.ReadWrite);
store.Add(newCert);
}
// reset ref and try to load it from manager
newCert = null;
newCert = this.GetCertificate(certName);
return newCert;
}
An Access is denied error appends when I try to add the certificate.
Any idea ? Can I store certificates into the Azure VM ?
Should I use a special location to store those ?
Are you using a Cloud Service (web/worker role)? If so, which OS family? I've seen some reports that with a worker role using OS family 3, you need to run the role with elevated permissions in order to read certs from the local cert store. Not sure if that applies to web roles as well and adding to the cert store.
Has the service cert been added via the Azure management portal as well (or via the REST API or PowerShell)?
Well I have found lot of things:
I was deploying my code in a web site so that I cannot add a certificate to the Shared VM in Azure
I have tried to connect to the VM in a remote desktop session and I added a certificate manually.
Even in this case, I have an (403) Forbidden error in an InvalidOperationException.
So here is the current state:
a certificate has been created (makecert) and added manually in the VM that hosts my web role (deployed in a service)
this certificate has been uploaded to both the Azure Account certificates and to the Azure service certificates (the one that deploys my web role)
the thumbprint of this certificate has been added in my code and I can access to the certificate when my code is executed
So 2 questions:
Is there something I should do with my certificate ?
When I try my web role locally in the Azure emulator, everything works. Is there a special setting to update during the publish / deploy step ?
Thanks for your help.
In order to save the time of other developers, here is what I did to solve the main problem:
connect to the VM that deploys the web role: see there
create the certificate: see there
Eventually plays with the certificates manager (mmc.exe)
Then the certificate is available from the code.

Resources