Using Consul with Azure App Services - azure

I'd like to have all of my configuration settings all in one place for all of my azure web app services, as well as resources outside of Azure. Consul's key value store seems like it could be a good fit (I'm happy to hear other suggestions if something else fits better). From my admittedly limited understanding of Consul, each node requires an agent to be running in order to access to key value store.
Is this correct? If so, how can I do this, would it be via a continuous webjob in Azure? If not, how can I access the KV store without an agent?

it looks like we will not be able to use consul with Azure App Service (aka Web Apps) at all.
Here is what I've tried.
1. Naive approach - consul as WebJob
Due to networking restrictions attempt to connect to ANY localhost ports what did not spawn with processes that belong to App Service (Web App) itself will end up with the following exception.
An attempt was made to access a socket in a way forbidden by its
access permissions 127.0.0.1:8500.
Reference from documentation:
https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox#networking-restrictionsconsiderations
The only way an application can be accessed via the internet is
through the already-exposed HTTP (80) and HTTPS (443) TCP ports;
applications may not listen on other ports for packets arriving from
the internet. However, applications may create a socket which can
listen for connections from within the sandbox. For example, two
processes within the same app may communicate with one another via TCP
sockets; connection attempts incoming from outside the sandbox, albeit
they be on the same machine, will fail. See the next topic for
additional detail.
Here is an interesting piece:
Connection attempts to local addresses (e.g. localhost, 127.0.0.1) and
the machine's own IP will fail, except if another process in the same
sandbox has created a listening socket on the destination port.
2. Consul spawned from App Service itself
I've copied consul to Web App (as build output) and added the following lines to application startup code:
var consul = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin/consul/consul.exe");
Process.Start(consul, "agent --data-dir=../../data");
Process.Start(consul, "join my-cluster-dns.name");
... and it joined the cluster and I even was able to connect to consul via 127.0.0.1:8500 from the App Service (Web App) itself.
However, it is still useless setup as Consul agent MUST be reachable from server, so all I was able to see from cluster standpoint is a dead node with failing "serf" health-check. Again, according to the documentation there is no work around this: "The only way an application can be accessed via the internet is through the already-exposed HTTP (80) and HTTPS (443) TCP ports".
https://www.consul.io/docs/agent/basics.html
Not all Consul agents in a cluster have to use the same port, but this address MUST
be reachable by all other nodes.
Summary
All-in-all, probably there is no way to properly host/use Consul with Azure App Services.

You don't need Consul Agent to retrieve configuration for your application.
You can use library Winton.Extensions.Configuration.Consul. It introduces Configuration Provider (docs) which can be integrated within your application.
Here sample configuration (full sample project available here)
internal sealed class Program
{
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host
.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(builder => builder.UseStartup<Startup>())
.ConfigureAppConfiguration(
builder =>
{
builder
.AddConsul(
"appsettings.json",
options =>
{
options.ConsulConfigurationOptions =
cco => { cco.Address = new Uri("http://consul:8500"); };
options.Optional = true;
options.PollWaitTime = TimeSpan.FromSeconds(5);
options.ReloadOnChange = true;
})
.AddEnvironmentVariables();
});
}
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
}
Your app configuration will be updated periodically.

Related

Using HTTPListener with Azure Web apps

I'm trying to get a simple HTTP console app running as an Azure Service App. All it does is return OK when you connect. It works fine on my laptop and I can publish to Azure ok using VS2019. The issue is the prefixes that are used for listening.
On my laptop I can use http://+:80/;https://+:443/, but in Azure I get an error: [EXCEPTION] Access is denied.
This article https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox#network-endpoint-listening implies the app will listen on 80 and 443
"The only way an application can be accessed via the internet is through the already-exposed HTTP (80) and HTTPS (443) TCP ports; applications may not listen on other ports for packets arriving from the internet.
However, applications may create a socket which can listen for connections from within the sandbox. For example, two processes within the same app may communicate with one another via TCP sockets; connection attempts incoming from outside the sandbox, albeit they be on the same machine, will fail. See the next topic for additional detail."
but my code always fails when I try and register the prefix. I can't use localhost as the same article says that's not allowed. I've tried using the app URL but that doesn't work either.
I've seen other articles that imply the HTTPListener needs admin permissions which I can't give it in Azure.
Does anyone know what the correct prefixes are or if it's ever going to work?
Netstat not working in KUDU so ASE (App Service Environment) is used to view the port details in portal App Service Environment -> General -> IP Addresses (check here ).
App Service applications only serve HTTP (port 80) and HTTPS (port 443) traffic. Each App Service application has default built-in HTTPS support for the azurewebsites.net domain name.
Your app may be already listening to the port 80 & 443. Please check here for more info for similar issue see here

C# How to RDP Connect to On Premise Windows Server from Azure App Services?

I have an Asp.net core web api hosted in azure app service. My web api should connect to one or many On Premise windows servers to create DNS records. The windows servers are running the DNS service. I am using System.Management to connect to the on premise windows servers.
However, I am not successful in connecting to the remote server from azure app service. I sure believe i am missing some kind of a configuration but I don't know..
Here is my code:
using System.Management;
public static ManagementScope ConnectDNSServer(string dnsServerName, PCSCredential useMyInfo)
{
ConnectionOptions options = new ConnectionOptions
{
Username = useMyInfo.WindowsDomain + "\\" + useMyInfo.UserName,
Password = useMyInfo.PassString
};
try
{
ManagementScope scope = new ManagementScope(#"\\" + dnsServerName + "\\root\\MicrosoftDNS", options);
scope.Connect();
return scope;
}
catch
{
//ManagementScope scopeEx = new ManagementScope();
}
return null;
}
I get this error:
System.Runtime.InteropServices.COMException (0x800706BA): The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
On Azure App Service - Regardless of address, applications cannot connect to anywhere using ports 445, 137, 138, and 139. In other words, even if connecting to a non-private IP address or the address of a virtual network, connections to ports 445, 137, 138, and 139 are not permitted.
Additional information, the standard/native Azure Web Apps run in a secure environment called a sandbox. Each app runs inside its own sandbox, isolating its execution from other instances on the same machine as well as providing an additional degree of security and privacy which would otherwise not be available. So, it appears to be due to Sandbox.
In this environment, the only way an application can be accessed via the internet is through the already-exposed HTTP (80) and HTTPS (443) TCP ports; applications may not listen on other ports for packets arriving from the internet.
Connection attempts to local addresses (e.g. localhost, 127.0.0.1) and the machine's own IP will fail, except if another process in the same sandbox has created a listening socket on the destination port:
https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox#network-endpoint-listening

How to start self-hosted OWIN Web API listening to a range of ports?

I'm running an Azure Worker Role that with self-hosted OWIN Web API
Currently, the host is initialized with a single URL like so:
var options = new StartOptions(endpoint);
_app = WebApp.Start<Startup>(options);
The endpoint has a port hard-coded in it. I'd like to have it listen on a range of ports.
My real issue is as follows:
My Web API host is not getting round-robined by Azure's load balancer. I believe this is because the default ("none") affinity setting uses SourceIP, Source Port, Target IP, Target Port, Protocol type to perform its load balancing. However, the clients to my Web API (in the thousands) are always the same clients - they connect every minute to perform some operations. Thus, these client's ports and IP's don't change. My listening port and IP do not change since the host is hard-coded to a port. All of the requests from these clients are getting round-robined to the same instance all the time. I've verified this over and over and over again. My first worker role instance gets all the traffic, as soon as 2nd instance is rebooted. 2nd instance never kicks in.
I would like to try to have my OWIN hosted Web API listen on a range of ports. Is this the right approach? If so, how can this be done?

Azure Multiple Public IPs on a Virtual Machine Scale Set with Resource Manager

We try to migrate our Platform from classical IIS hosting to a service fabric micro service architecture. So fare we learned that a service fabric lives in a virtual machine scale set and uses Load balancer to communicate to the outside world.
The Problem we now facing is that we have different access points to our application. Like one for browser, one for mobile app. Both use the standard https port, but are different applications.
In iis we could use host headers to direct traffic to one or the other application. But with service fabric we can’t. easiest way for us would be multiple public IP’s. With that we could handle it with dns.
We considered a couple solutions with no success.
Load balancer with Multiple public ip’s. Problem: it looks like that only works with Cloud Services and we need to work with the new Resource Manager World there it seems to be not possible to have multiple public ip’s.
Multiple public load balancer. Problem: Scale Sets accept only on load balancer instance pert load balancer type.
Application Gateway. Seems not to support multiple public ip’s or host header mapping.
Path mapping. Problem: we have the same path in different applications.
My questions are:
Is there any solution to use multiple IP’s and map the traffic internally to different ports?
Is there any option to use host header mapping with service fabric?
Any suggestion how I can solve my problem?
Piling on some Service Fabric-specific info to Eli's answer: Yes you can do all of this and use an http.sys-based self-hosted web server to host multiple sites using different host names on a single VIP, such as Katana or WebListener in ASP.NET Core 1.
The piece to this that is currently missing in Service Fabric is a way to configure the hostname in your endpoint definition in ServiceManifest.xml. Service Fabric services run under Network Service by default on Windows, which means the service will not have access to create a URL ACL for the URL it wants to open an endpoint on. To help with that, when you specify an HTTP endpoint in an endpoint definition in ServiceManifest.xml, Service Fabric automatically creates the URL ACL for you. But currently, there is no place to specify a hostname, so Service Fabric uses "+", which is the strong wildcard that matches everything.
For now, this is merely an inconvenience because you'll have to create a setup entry point with your service that runs under elevated privileges to run netsh to setup the URL ACL manually.
We do plan on adding a hostname field in ServiceManifest.xml to make this easier.
It's definitely possible to use ARM templates to deploy a Service Fabric cluster with multiple IPs. You'll just have to tweak the template a bit:
Create multiple IP address resources (e.g. using copy) - make sure you review all the resources using the IP and modify them appropriately
In the load balancer:
Add multiple frontendIPConfigurations, each tied to its own IP
Add loadBalancingRules for each port you want to redirect to the VMs from a specific frontend IP configuration
Add probes
As for host header mapping, this is handled by the Windows HTTP Server API (see this article). All you have to do is use a specific host name (or even a URL path) when configuring an HTTP listener URL (in OWIN/ASP.NET Core).

Database hosted in Azure virtual machine is the same as if hosted on normal remote hosts?

I would like to host a firebird database in an Azure virtual machine.
Normally, I would indicate in a program a connection like this:
hostname:databasename
....to connect to remote host. In azure, you cannot do that.
I would need to connect with something like:
?.cloudapp.net:someport:databasename
The client would be talking to ?.cloudapp.net thinking that someport is the port to communicate with the database server.
So it seems I would need a proxy to login-connect to windows azure cloud resources and the client would then use the proxy to talk with the database server. This looks like a hassle - are there any alternatives?
I'm not entirely sure of your Cloud architecture in Azure, but assuming you have one VM with your DB installed you should be able to open up a a public endpoint (via the portal manage.windowsazure.com for your Cloud Service) and connect to that via it's public IP address & the port).
Windows Azure does have more advanced features that allows you to connect to specific VM's within a Cloud Service via Port Forwarding.
Michael Washam has a great blog post on this 'Windows Azure Virtual Machines':
http://michaelwasham.com/2012/06/08/understanding-windows-azure-virtual-machines/
The architecture of cloud services makes endpoint configuration
interesting. Since each cloud service has a single public IP address
but multiple virtual machines can reside in it how do you address
individual servers directly in a non-load balanced fashion?
Port forwarding allows you to configure an endpoint on a specific VM
listening on any of the ephemeral ports that will then be forwarded to
the correct internal port.

Resources