I need to call a REST API from azure function app which requires a client certificate.
I followed this How to manage signed certificates with Azure Function V2 and did below steps:-
1)I have uploaded my private key certificate(.PFX) in TLS/SSL settings under private key certificate.
2)Added a key under configuration/application settings for
WEBSITE_LOAD_CERTIFICATES: "My Cert Thumbprint"
Then I tried to access the certificate in my code using this
using System;
using System.Security.Cryptography.X509Certificates;
...
X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
// Replace below with your certificate's thumbprint
"000000000000000000000000000000000000000",
false);
// Get the first cert with the thumbprint
if (certCollection.Count > 0)
{
X509Certificate2 cert = certCollection[0];
// Use certificate
Console.WriteLine(cert.FriendlyName);
}
certStore.Close();
...
I don't get back any certificate. What am I doing wrong?
If I upload a public certificate(.cer), I am able to access the certificate but it doesn't have the private key so I am unable to call the service.
First, please check if you have copy the Thumbprint(in below screenshot) to your function application settings WEBSITE_LOAD_CERTIFICATES.
Then please test with some other fields of cert in your code because sometimes the certificate doesn't have FriendlyName. I test in my side and it shows nothing for FriendlyName. Then I test with Issuer, it works fine.(Notice I use log.LogInformation(cert.Issuer); instead of Console.WriteLine(cert.Issuer); because I find Console.WriteLine shows nothing)
Related
I am working on Azure Functions App on Consumption Plan. The Func App required to load a specific signed certificate.
In local machine I setup the certificate as personal certificate and everything works fine.
After publishing on azure, I am getting this error:
There are 0 certificates with the subject name cert.name in LocalMachine, MyUse scripts/certificates/ to generate this
Nothing helpful on SO or even in Azure Func documentation on how to use certificate with azure functions.
Anyone has experience with that?
I got it and it's pretty straight forward.
First go to platform features under your Function App and you should find SSL as shown below.
Then you can add a public, private or SSL certificate based on your needs. In my case I want to add a private Certificate which i already exported and have it's private key.
After uploading your certificate, go to your app settings and add this key/value:
WEBSITE_LOAD_CERTIFICATES: "Your Cert Thumbprint"
You should be able to load the certificate using this Thumbprint like this:
using System;
using System.Security.Cryptography.X509Certificates;
...
X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
// Replace below with your certificate's thumbprint
"000000000000000000000000000000000000000",
false);
// Get the first cert with the thumbprint
if (certCollection.Count > 0)
{
X509Certificate2 cert = certCollection[0];
// Use certificate
Console.WriteLine(cert.FriendlyName);
}
certStore.Close();
...
I have a B1 App Service in Azure and I've installed my certificate in it as shown below:
When I try to get the certificate, it can't find it. As if no certificates are installed. Here's my code:
using (X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
certificateThumbprint,
false);
if (certCollection.Count > 0)
{
return certCollection[0];
}
throw new Exception("Certificate not found!");
}
I've verified the certificate thumbprint and even tried putting it hard-coded as string.
When I try to print the number of certificates in the store like this:
Console.WriteLine("certStore.Certificates.Count : " + certStore.Certificates.Count);
it returns zero certificates.
I also tried changing StoreName and StoreLocation - still same result. And even when not giving any StoreName or StoreLocation it still doesn't find any certificates.
You need to add an app setting called: WEBSITE_LOAD_CERTIFICATES
From https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/?v=17.23h:
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 “ * “ (without quotes) in which case all your certificates will be loaded to your web applications personal certificate store.
I have a .NET Core application that I'm trying to deploy to Azure App Service. When I deploy and try to load the site I'm getting a 502.5 error response. From what I've read that means it's a permissions issue. I've tried printing the logs with stdout, but while it physically creating the log files, they are all empty.
So I started eliminating the problem by commenting out code. On ConfigureServices I'm loading a certificate:
var certificate = new X509Certificate2("mycertificate.pfx", "**********");
If I comment out this line, then the application loads. Once returned it gives the error again.
From console in the Azure portal I've tried giving mycertificate.pfx permissions using chmod 777 mycertificate.pfx, but it didn't seem to have any affect.
I'm not sure if the problem is loading that specific file or using X509Certificate2 at all.
How can I set it up to work?
How can I set it up to work?
1.Upload pfx Certificate to the Azure with azure portal. It is required service plan B or above. How to change service plan please refer to this document
Add 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 “ * “ (without quotes) in which case all your certificates will be loaded to your web applications personal certificate store
3.Access from WebApp
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();
}
}
}
We could get more info from document.
I have a very strange problem. I published a webrole to azure cloud service. In this project, it requires webrole call a Azure Rest API, I can get the response in local emulator but, if I publish it to Azure I get the 403 forbidden Error. I am sure that I installed the certificate to Azure.
This error can be reproduced with following steps:
First create a certificate with link below: http://msdn.microsoft.com/en-us/library/windowsazure/gg651127.aspx
Create a cloud service with a webrole, and the certificate in Azure portal, cloud service Certificate and webrole->property->certificate.
Publish the project.
Remote log in to the web role instance.
Create a console application at local then copy the debug folder to remote instance and run the exe in remote application. you can find the application can run perfect in local, but in Azure instance, it seems like it can find certificate, but still get 403 forbidden error.
Console app code:
static void Main(string[] args)
{
try
{
// X.509 certificate variables.
X509Store certStore = null;
X509Certificate2Collection certCollection = null;
X509Certificate2 certificate = null;
// Request and response variables.
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebResponse = null;
// Stream variables.
Stream responseStream = null;
StreamReader reader = null;
// URI variable.
Uri requestUri = null;
// Specify operation to use for the service management call.
// This sample will use the operation for listing the hosted services.
string operation = "hostedservices";
// The ID for the Windows Azure subscription.
string subscriptionId = "";
// The thumbprint for the certificate. This certificate would have been
// previously added as a management certificate within the Windows Azure management portal.
string thumbPrint = "";
// Open the certificate store for the current user.
certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
// Find the certificate with the specified thumbprint.
certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
thumbPrint,
false);
// Close the certificate store.
certStore.Close();
// Check to see if a matching certificate was found.
if (0 == certCollection.Count)
{
throw new Exception("No certificate found containing thumbprint " + thumbPrint);
}
// A matching certificate was found.
certificate = certCollection[0];
Console.WriteLine("Using certificate with thumbprint: " + thumbPrint);
// Create the request.
requestUri = new Uri("https://management.core.windows.net/"
+ subscriptionId
+ "/services/"
+ operation);
httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(requestUri);
// Add the certificate to the request.
httpWebRequest.ClientCertificates.Add(certificate);
// Specify the version information in the header.
httpWebRequest.Headers.Add("x-ms-version", "2011-10-01");
// Make the call using the web request.
httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
// Display the web response status code.
Console.WriteLine("Response status code: " + httpWebResponse.StatusCode);
// Display the request ID returned by Windows Azure.
if (null != httpWebResponse.Headers)
{
Console.WriteLine("x-ms-request-id: "
+ httpWebResponse.Headers["x-ms-request-id"]);
}
// Parse the web response.
responseStream = httpWebResponse.GetResponseStream();
reader = new StreamReader(responseStream);
// Display the raw response.
Console.WriteLine("Response output:");
Console.WriteLine(reader.ReadToEnd());
// Close the resources no longer needed.
httpWebResponse.Close();
responseStream.Close();
reader.Close();
}
catch (Exception e)
{
Console.WriteLine("Error encountered: " + e.Message);
// Exit the application with exit code 1.
Console.ReadLine();
System.Environment.Exit(1);
}
finally
{
// Exit the application.
Console.ReadLine();
System.Environment.Exit(0);
}
}
I was running into the same issue using the azure create cert link you provided. I found out that when creating the certificate using that method, the private key was not being uploaded to the cloud service. Even though the service was able to find the certificate, it was still unauthorized when submitting requests.
Using the following method to create a private and public key certificate worked. In the Visual Studio Command Prompt, create a .cer and .pfx file:
makecert -r -pe -n "CN=AzureManage" -sky exchange "AzureManage.cer" -sv "AzureManage.pvk"
pvk2pfx -pvk "AzureManage.pvk" -spc "AzureManage.cer" -pfx "AzureManage.pfx" -pi password
The first command creates a private and public key file. You will be prompted for a password a few times. The second command combines the two into a pfx file. If you leave -pi password off, then you will be prompted for the password instead of entering it in the terminal.
You'll then want to import the files appropriately:
Import the pfx into your Local Machine / Personal certificate store using mmc.
Upload the pfx to the Azure Cloud Service.
Upload the cer to the Azure Management Certificates store.
Add the thumbprint of the pfx to your Azure Role Certificates property.
You can then use the Azure management REST API as follows:
X509Certificate2 GetCertificate(string thumbprint)
{
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (certs.Count == 0) return null;
var cert = certs[0];
store.Close();
return cert;
}
HttpWebRequest request = WebRequest.CreateHttp(apiUrl);
request.ClientCertificates.Add(cert);
request.Headers.Add("x-ms-version", "2012-03-01");
I believe your problem lies with this line of code:
certStore = new X509Store(StoreName.My, **StoreLocation.CurrentUser**);
I would expect that a properly uploaded certificate (assuming it was a .pfx that uploaded properly thru the management portal) is stored in the LocalMachine store, not CurrentUser.
Also, in order to read the certificate from the certificate store, your Role needs to run in Full Trust (this can be specified/validated in the Role's project properties in visual studio)
+1 #Igorek. I faced similar problem. If I specify that the certificate should be installed in CurrentUser store in my configuration, I found that for a Web role the certifcate installs there but for the Worker role the certificate is installed in the LocalUser store.
However looks like this is not the root cause of the problem. Can you ensure that the same certificate is there under Management Certificates section in the portal (exporting it 1st in cer file format and uploading it there) and the certificate installed in the role has private properties attached to it. These two reasons are primary cause of 403 error.
I have an Azure Worker Role that I wish to call the Management Service (e.g. REST API) and collect information regarding related services. However, when I try to load my certificate it fails to find it. Here are the steps I followed:
1. I created a certificate using MakeCert and registered it as my Management Certificate via the portal
makecert -r -pe -a sha1 -n "CN=MyCnName" -ss My -len 2048
-sp "Microsoft Enhanced RSA and AES Cryptographic Provider" -sy 24 MyCert.cer
2. Installed the cert on my local machine and everything works fine. When running the Worker Role locally I can call the Management Service with no problems.
3. Exported the cert from my machine and registered the exported certificate under the target Hosted Service via the portal
4. Deployed the Role. When the Role starts it fails to find the cert.
Here is an extract of the code I'm using to find the cert.
// Open the certificate store for the current user.
var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); // I also tried localmachine
certStore.Open(OpenFlags.ReadOnly);
// Find the certificate with the specified subject.
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindBySubjectName,
_myConfiguration.SubjectName,
false);
if (certCollection == null || certCollection.Count < 1)
{
// Find the certificate with the specified thumbprint.
certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
_myConfiguration.ThumbPrint,
false);
}
// Close the certificate store.
certStore.Close();
// Check to see if a matching certificate was found.
if (certCollection.Count == 0)
{
_logger.Warn("No certificate found");
}
There is no exception, just no cert is found. Can anyone shed some light I what I need to do?
Figured out the problem... In addition to configuring the cert in the portal, I needed to add the certificate details (e.g. Name, Store, and Thumbprint) to the Azure Project Role settings under the Certificates Tab.
I have a similar problem for a web role, i have applied a workaround.
Connect with remote desktop to the VM where the service and
certificate are deployed
List item
Copy your cert or pfx on your
VM local disk (e.g C:)
Click on your pfx or .cert file and
install it on the specific certificate store "Trusted People")
Run your service, even if you are configured for search on a different
store you will find on trusted people
I don't know why my web role try to find the cert on this location if I am forcing to search on "My Store" location but the search method retrieve info from trusted people store.
The problem with this workaround is when you delete your deployment the cert and any other configuration will be wiped.
This piece of code could give you some information:
//the certificate must be in the Trusted People Store
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
//Commented
//Get the first available match from cert store
//X509Certificate2 cert = store.Certificates.Find(X509FindType.FindBySubjectName,
// subjectname,
// false)
// .Cast<X509Certificate2>()
// .FirstOrDefault();
X509Certificate2 cert = new X509Certificate2();
foreach (var ct in store.Certificates)
{
//Logger.TraceInformation(string.Format("Cert found: Subject {0} Tumbprt:{1}", ct.FriendlyName, ct.Thumbprint));
if (ct.SubjectName.Name.ToString().Contains("*.certnamexx.extensionxx"))
{
return new X509SecurityToken(ct);
}
}
}