How to disable Weak Ciphers from Azure mobile service? - iis

Is there any way to disable weak ciphers from Azure Mobile Service?
The service is running in Standard tier.
Publish server port is 443.
I tried to run following code
string[] subKeys = new string[]
{
"RC4 40/128",
"RC4 56/128",
"RC4 64/128",
"RC4 128/128",
};
RegistryKey parentKey = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers", true);
foreach (string keyName in subKeys)
{
var newKey = parentKey.CreateSubKey(keyName);
newKey.SetValue("Enabled", 0);
newKey.Close();
}
parentKey.Close();
refered from How to disable RC4 cipher on Azure Web Roles
But getting Requested registry access is not allowed exception
It is mentioned in same link to add executionContext="elevated" in the startup
I'm not sure where to add this line or how to apply web role to mobile service..

This is not something you can control within Azure Mobile Services. Check out this question on testing which ciphers are allowed: https://superuser.com/questions/109213/how-do-i-list-the-ssl-tls-cipher-suites-a-particular-website-offers

Related

How to ask DefaultAzureCredential to use my user credential locally

I'm trying to develop a web app on an Azure VM that uses Azure Key Vault. Later this app will also be deployed to Azure. As far as I know, the most straight forward way to make the app work, both locally and deployed, with the key vault, is to use the DefaultAzureCredential class. The code would be like this:
string kvUri = "https://" + keyvaultName + ".vault.azure.net";
SecretClient client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
KeyVaultSecret secret = await client.GetSecretAsync(secretName);
At runtime, the provider will try different credential types in order.
This sounds exactly what I want:
When developing locally (on the Azure VM, though), I want to use my user credential (user identity added to the key vault's permission) without any configuration, since I have already logged into the Visual Studio using the same user credential.
Once deployed to Azure, I want to use the app registration credential (also added to the key vault's permission).
But when running the app locally, I'm getting a 403 error The user, group or application .... does not have secrets get permission on key vault ...
After looking up the object id in the error message, I realize it's the dev machine Azure VM's credential that the application uses, not my user credential.
Is there a way to change this behavior?
To prevent the Azure VM from getting a token, you can exclude the ManagedIdentityCredential in your Development environment and only enable it in a Non-Development environment.
if (environment.IsDevelopment())
{
var credentials = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ExcludeManagedIdentityCredential = true,
ExcludeAzureCliCredential = true
});
}
else
{
var credentials = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ExcludeVisualStudioCodeCredential = true,
ExcludeVisualStudioCredential = true
});
}
Once deployed to Azure, I want to use the app registration credential (also added to the key vault's permission).
An Azure App Service can use a managed identity as well. There is no need for a separate App Registration.
See https://learn.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme#key-concepts for more information.
Create and identity if you wish to use (default identity)
appservice -> select you application -> identity->enable it ->should give you a Id
and than add it to key Vault Access policy
alternatively app registration can be used with tenantId,clientId,secret to connect to keyvault

What's the best/latest approach to authenticate access to Azure Key Vault using Certificate from an non-azure application

I would like to retrieve Azure Key Vault secrets from a client application(outside of Azure) using certificate authentication for Azure Key Vault through Azure AD. My initial development is done through a dotnet console application, and eventually, I would like to use similar logic within a WCF web service hosted on an IIS server outside Azure (an on-premise server). I have everything set up on cloud side: Azure Key Vault set up, client application registration, and a certificate within Azure Key Vault for client Application authentication. I also install the same certificate in my local machine current user certificate store and the certificate on the windows service server hosting my WCF web service. So that I can retrieve the certificate from the certificate by using its thumbprint value:
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, onlyAllowValidCerts);
I tried a couple of approaches to access Azure Key Vault secrets, but nothing has met the expectations I set up initially. I would like to know what is the best/latest approach to achieve what I want without compromising response time and using deprecated APIs
Use AzureKeyVaultConfigurationProvider to retrieve secrets
Issues:
1.1)I have to use a few deprecated packages for this purpose.
1.2)Also, the performance (response time) to retrieve the secrets from Azure Key Vault and populate the AzureKeyVaultConfiguration is not ideal...
Code Example:
// create IConfigurationRoot to read Azure key vault
IConfigurationRoot config = new ConfigurationBuilder()
.AddAzureKeyVault(
keyVaultUrl,
CLIENT_ID,
KeyVaultUtility.AssertionCert2,
new DefaultKeyVaultSecretManager())
.Build();
Use AzureKeyVault package to create a KeyVault Utility. Then use GetSecretAsync method:
Issues: 1)Azure Key Vault package is deprecated
2)When I use this logic with WCF service, and test locally, I run into following error:
Method not found: 'Void Microsoft.Azure.KeyVault.KeyVaultClient..ctor(AuthenticationCallback, System.Net.Http.DelegatingHandler[])'.
Code Example:
var client = KeyVaultUtility.GetClient();
var secret = Task.Run(async () => await client.GetSecretAsync(keyVaultUrl, "Jon--Test")).Result.Value;
KeyVaultUtility logic:
public static KeyVaultClient GetClient()
{
if (AssertionCert == null)
{
throw new Exception("Call Initialise before calling GetClient.");
}
return new KeyVaultClient(new KeyVaultClient.AuthenticationCallback((a, r, s) => GetAccessToken(a, r, s, AssertionCert)));
}
private static async Task<string> GetAccessToken(string authority, string resource, string scope, ClientAssertionCertificate cert)
{
var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
var result = await context.AcquireTokenAsync(resource, cert).ConfigureAwait(false);
return result.AccessToken;
}

Azure Functions - Configure client certificate authentication

Do functions support authorizing access to a Function by using client certificates, in a consumption plan? Something similar to the approach described here? Basically, I'm looking for the Functions runtime to immediately reject connection requests if the caller does not present a valid client certificate, without me having to implement that authorization routine in the code.
Here's the code I came up with, note: this is for Azure Functions v1, when req is an HttpRequestMessage
Caller:
X509Certificate2 clientCert = req.GetClientCertificate();
if (!IsValidClientCertificate(clientCert))
{
return req.CreateErrorResponse(HttpStatusCode.Unauthorized, "A valid client certificate is not found");
}
For Azure Functions v2, you can get the client certificate from the HttpRequest using req.HttpContext.Connection.ClientCertificate
Basic validation function:
static bool IsValidClientCertificate(X509Certificate2 clientCert)
{
// check the cert's thumbprint against expected thumbprint
if (clientCert.Thumbprint != "<expected thumprint>"
{
return false;
}
// check that we're within the cert's validity period
if (DateTime.Now > clientCert.NotAfter || DateTime.Now < clientCert.NotBefore)
{
return false;
}
// optionally check cert chaining validity
// if(!clientCert.Verify()) { return false; }
}
Based on your requirement, I created my C# HttpTrigger function to check this issue, here is the core code:
if(req.Headers.Contains("X-ARR-ClientCert"))
{
byte[] clientCertBytes = Convert.FromBase64String(req.Headers.GetValues("X-ARR-ClientCert").FirstOrDefault());
var clientCert = new X509Certificate2(clientCertBytes);
return req.CreateResponse(HttpStatusCode.OK,"Thumbprint: "+clientCert.Thumbprint);
}
return req.CreateResponse(HttpStatusCode.OK, "Hello world");
For App Service Plan, the function could work as follows:
Per my test, the function could also work as expected under the consumption plan.
You could follow How To Configure TLS Mutual Authentication for Web App or just log into Azure Portal and go to your function app, click "NETWORKIING > SSL" under Platform fetures tab, then enable Incoming client certificate option.
Yes it does. If I understand you correctly, you want to reject with a 403, any https requests without a client cert
This is how to enable it with Azure CLI
az webapp update --set clientCertEnabled=true --name <app_name> --resource-group <group_name>
Microsoft docs here
You can also do this from the Azure Portal, under Azure Function App => Configuration => General Settings

Azure appservice with Client certificate based or AAD token based authentication

Need client certificate based or AAD token based authentication enabled web api hosted in azure app service.
I am migrating one web API from classic cloud service to azure app service.
The API supports calls with valid certificates or valid AAD token.
Code is given below:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
ClaimsPrincipal principal;
var cert = request.GetClientCertificate();
if (cert != null)
{
//authenticate client certificate
//Set principal from client certificate
}
else
{
//get AAD token
//authenticate & set principal
}
return await base.SendAsync(request, cancellationToken);
}
The issue is in App service for certificate based calls request.GetClientCertificate() is returning null instead of X509Certificate2 object. So not able to authenticate certificate based calls.
I have tried below link as well but in that case calling without certificate is not possible as its making required SSL certificate on for whole website.
https://learn.microsoft.com/en-us/azure/app-service-web/app-service-web-configure-tls-mutual-auth
There are lot of details missing in your explanation. The shared code snippet is useless.
In Azure App Service, there is a which sits in front of the VM where the application is hosted. When you enable TLS Mutual Auth for your web app, it is enabled for the entire app. Currently there is no option to do it for specific pages or sub-folders.
When the clients accesses the site, the Front-End prompts them for the client certificate. Assuming the client provides the certificate to the Front-End, it then passes this certificate to the back end VM in the form of a host header "X-ARR-ClientCert".
I dont see this being used anywhere in the above code snippet. This is also explained in the article (Azure App Service TLS Mutual Auth) which you have linked in your question:
protected void Page_Load(object sender, EventArgs e)
{
NameValueCollection headers = base.Request.Headers;
certHeader = headers["X-ARR-ClientCert"];
if (!String.IsNullOrEmpty(certHeader))
{
try
{
byte[] clientCertBytes = Convert.FromBase64String(certHeader);
certificate = new X509Certificate2(clientCertBytes);
You need to read the contents X-ARR-ClientCert header and then convert it to a X509Certificate2 object and then run your checks against this.

Certificate Problem (Security Related?!?)

I'm trying to enumerate certificates from Azure within a web role (running on the v1.3 Azure SDK Dev Fabric) but no certificates are returned when I use the following code. It's important to note, however, that code works fine when run from a console program:
private static void EnumCerts()
{
var selectedCerts = new X509Certificate2Collection();
var store = new X509Store(
StoreName.My, StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
foreach (X509Certificate2 cert in store.Certificates)
Console.WriteLine(cert.Subject);
}
finally
{
store.Close();
}
}
My working assumption is that this is due to a security issue. My web role is running with Elevated Trust but I'm guessing that the IIS web instances are not.
In either case I have no idea how to solve the problem, so any help would be greatly appreciated...
Store the X509 certificate in the LocalMachine instead of CurrentUser. CurrentUser for an IIS process runs within the context of IIS-user who you likely have no access to.
Also, you want to make sure that you've imported the certificate on the Azure side into certificate store properly by remoting-in and verifying.
You should remote (RDP) into the role and check the store(s). I honestly don't know where Azure portal uploads certs, but I thought it was CurrentUser (which I think IIS runs under as well).
You can also enumerate the certificates via the Service Management API, which may or may not work for your solution. http://msdn.microsoft.com/en-us/library/ee795178.aspx
I ended up solving the problem by embedding the certificate in my service code then reading it from the resource:
using System.IO;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
namespace AcsTest.Shared
{
public static class CertHelper
{
public static X509Certificate2 GetCertFromManifest(
Assembly assembly, string certName, string password)
{
byte[] bytes;
using (var stream = assembly.
GetManifestResourceStream(certName))
{
bytes = new BinaryReader(stream).
ReadBytes((int)stream.Length);
}
return new X509Certificate2(bytes, password,
X509KeyStorageFlags.MachineKeySet);
}
}
}
The key insight was that I'd need to store a password in my service to load the cert from the certificate store so I was gaining no security advantage by keeping it in the store.

Resources