Azure AD authentication from inside a Container

I’m having problems getting Azure AD logins to work on my dashboard. I have it running in a linux container. Locally this is no problem and works great! When I push it to Azure and run it, it doesn’t work. The login page loads up, then I get this error message:

These are my redirect uris:

What’s interesting is that it seems like its trying to go to the first redirect uri (not localhost) but without the ‘s’ in https… which is required for a redirect uri.

This is the final part of my dashboard:

$DashboardParameters = @{
    Title                  = "Panorama"
    Pages                  = $Pages
    Navigation             = . (Join-Path -Path (Join-Path -Path $Cache:RootPath -ChildPath navigation) -ChildPath navigation.ps1)
    Theme                  = . (Join-Path -Path (Join-Path -Path $Cache:RootPath -ChildPath theme) -ChildPath theme.ps1)
    Footer                 = New-UDFooter -Copyright ""
    EndpointInitialization = $EndPointInitialization
    LoginPage              = $LoginPage
}

$Dashboard = New-UDDashboard @DashboardParameters
Start-UDDashboard -Dashboard $Dashboard -Port $port -PublishedFolder $Folder -Wait - 
AdminMode -AllowHttpForLogin 

Is this because of the -AllowHttpForLogin? If I take that off, it won’t work without a certificate, which I’ve tried using self-signed ones, but I can’t seem to get that to work either.

If I add an ‘s’ to the url in the redirecturi query string after attempting to log in, it works… curious.

Any help is greatly appreciated. I’m hoping this won’t come down to a cert issue, but I think it will. None of the examples involving UD and containers include dealing with certs…

I have also tried creating a self-signed cert locally and just putting that into the container and using the -CertificateFile and -CertificateFilePassword params. This seems to work when running locally but not when it’s in the Linux container locally.

This is likely a cert issue :slight_smile:

UD won’t be listening on HTTPS if you haven’t set a cert. So what’s probably happening is that the redirect_uri is being set to HTTP because UD isn’t listening on HTTPS but Azure is expecting a redirect_uri of HTTPS since that’s what’s configured in the portal.

Are there any examples of using a cert with ID in a Linux container hosted on Azure? I’ve tried a bunch of different methods but so far nothing. Unfortunately I think my issue is a lack of understanding of certs.

I have a need for this but haven’t done ti yet so don’t have an example. I have a dashboard for Universal Automation that’s running in Azure in a docker container but I don’t have HTTPS hooked up for it. I’ll have to take a look into it soon and will blog\post about it when I figure it out.

Cool, sounds good. I’m going to continue to look into it because I really want to get Azure AD working with this. If I figure it out I’ll let you know.

Have you tried to get the Cert working locally? IE running your UD on your local PC with the self-signed/public cert installed?

I have some spare time today and tomorrow between meetings, I will dig back into this as I too would like to host my UD in a container as I tried this months back but gave up :frowning:

Ok I got it. Easier then I thought it was just coming at it with fresh eyes.

So first I generated a Self-Signed Certificate (Locally on PC) using this cmdlet

New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName “ud.domain.com” -FriendlyName “ud.domain.com” -NotAfter (Get-Date).AddYears(1)

the DNS name will obviously need to exist this is where your reply_url will come from during Azure AD Auth.

Next export the Certificate from your local PC Certificate Store into a PFX. Make sure you click to export the private key during the export. you will also need to set a password which will be used by UD to import/use the certificate.

Once you have the certtificate.pfx add this to your Start-UDDashboard

-CertificateFile ‘/path/certtificate.pfx’ -CertificateFilePassword (ConvertTo-SecureString “pfxpassword” -AsPlainText -Force)

This will start your Dashboard using the pfx certificate. Once you start your Dashboard (would test locally) you will see that the Dashboard was started on port 443

Also make sure that the Service Principal in Azure that is being used for the UD Auth has the URL you used during your certificate creation.

I offically have this now working with Azure AD Auhentication running in a Docker Container.

2 Likes

This helped immensely, thank you so much!

My redirect works locally now on https://localhost, but now when it’s in Azure the site doesn’t come up at all.

I was running my site on port 10001, and the container logs show this:

Container panorama_0_3bc4374d didn't respond to HTTP pings on port: 10001, failing site start. 

I’m not running Kubernetes, just the Azure Web App for Container. I’m going to try just running it on 443. I had to add an App Setting WEBSITES_PORT = 10001 for the site to come up originally. Time for some more troubleshooting.

Maybe I need to set up http to https redirect?

I find the Azure Web App for Containers is problematic. I haven’t used it with UD, but other web applications we have running in containers did NOT like the proxying that was done by the Azure Platform.

Some things to try ( I would need to dig into the Web App as we use Kubernetes)
By the error your getting sounds like the App Service cannot communicate with your UD on port 10001. try specifying the port within your Start-UDDashboard

-Port 10001 -HttpsPort 443

or something to that effect - what you need to accomplish is 443 on the outside (as this is done by the Web App Platform) but be able to accept communication on another port such as 10001 or 80.

** Edit - Also check your Web App Logs (Under Advanced Tools, Log Stream) and see if you can see UD starting… you should be able to see Start-UD output which will confirm that it’s just a port/proxy issue. Also try and set your EXPOSE port in your dockerfile.

Let me see what I can dig up. I have a lab environment I can test with. Lets see if we can figure this out… Maybe adam can write a doc page on this once we figure it out :slight_smile:

So I tried doing -port 80 -https port 443 and the logs told me it worked

019-11-27T21:20:50.496313190Z Hosting environment: Production
2019-11-27T21:20:50.497428292Z Content root path: /root/.local/share/powershell/Modules/UniversalDashboard/2.7.0/netstandard2.0/../client
2019-11-27T21:20:50.498290493Z Now listening on: http://0.0.0.0:80
2019-11-27T21:20:50.498567194Z Now listening on: https://0.0.0.0:443
2019-11-27T21:20:50.499379695Z Application started. Press Ctrl+C to shut down.

But the site didn’t actually come up when visiting the url. I’m going to try just using -port 80. Maybe the proxy is handled by the Web App framework itself and by specifying -https 443 its wrong. The app setting I had set earlier (based on a tutorial for running UD in a container) was WEBSITES_PORT. I removed that and now its looking for 80.

EDIT:

Current state:

In my dockerfile I exposed 80 and 443. In my dashboard.ps1 i have -port 80 and -httpsport 443. When I go to the site I get this:

panorama.azurewebsites.net redirected you too many times.

It seems like Azure Web App for containers pings via HTTP on the port specified by the WEBSITES_PORT configuration. So if I have a site meaning to run on https, it must be different than the http port, but this starts a redirect loop (dev tools in chrome shows a ton of 308s). I have it set to https only in my app settings as well, but I’m not sure how to get around this.

EDIT:

UD with a cert/https might not work on Azure Web App for Containers. You can only expose one port to the world, and it seems like it needs to ping it on http to start the container, meaning you can only expose the http port…

So either we need a way to enable the redirect uris to be https even when not running with a cert (which I think is okay since Azure is dealing with the certs in this case) or wait until Microsoft adds support for exposing more than one port on their Web App for Containers platform…

EDIT: I spun it up using Azure Container Instances and it worked, but this doesn’t actually provide SSL. Ugh.

Yeah I was doing some reading on the Azure Web App for Containers and I found the same - only 1 port, and http required as a ping port to bring up the container. Hence why we shied away from them and went to K8s.

I did just try the UD Container in a Container Instance and that did work. And I do get SSL (see snip below - showing my self-signed from earlier)… What do you get when using a container instance?

Yeah that’s exactly what I got, I guess more specifically I should say it servers https, but its not secure. But I’m on the right track! Now I just need to get a trusted cert. I might try using nginx via this blog post: https://powershell.org/2019/03/running-universal-dashboard-with-ubuntu-and-nginx-with-https/

We actually use k8s for some other apps here, but as this is primarily going to be used internally and by Ops/Support, I wanted it to be easier to contribute to, hence UD instead of asking ops guys to learn C# or something to add to the web app, and hence a single container app and not full blown orchestration.

Oh that “Not Secure” is easy. I just got lazy with the root certicicate.

Certificate 101 - Any certificate can be trusted. All trusts are provided by the top level certificate authority. and any certificate in that chain will be trusted automatically.

Notice when you go to any secure website, click the certification path, you will see there is 2-3 certificates in the chain. In most public certificate authorities they have a root then intermediate/child certificates.

So with our self-signed certificate we need to install that into our root certificates folder. so our local PC trusts that certificate to make it “secure”. Note this will only show secure on the local PCs you install that self-signed as a root certificate. you might be better (if will be used publically) is getting a free certificate from https://letsencrypt.org/ or if its going to be an internal application maybe using an internal PKI to provide the certificate as Corporate PKI root certificates are normally trusted throughout the organization.

Open Certificate Manager on your PC (Windows) and make sure you open your Computer Store. Open your Personal folder and find your self-signed certificare from yesterday and click copy. Next, open the Trusted Root Certificate Authority folder, right click and select paste. you will now see your self-signed certificate in your Root Folder (see below).

Close your brower and relaunch to your container URL and you will see it now shows secure.

1 Like

So, presumably I should be able to use LetsEncrypt to get a cert, output a pfx somehow, and then use that in the Start-UDDashboard command for it to be used publicly? Most of the stuff I look up regarding containers/letsencrypt deal with nginx, and I’ve got UD to run with nginx before, but not with a cert, and UD needs the pfx in order for the redirect to be correct for Azure AD logins. (I realize we’re leaving the realm of UD a little bit here, but this is a very unique situation without documentation or random stack overflow posts. Totally appreciate any amount of help given. I will probably write something up once this is all done and/or publish a container image once this is all figured out).

Issues I’m currently running into:

If I try to manually make a cert with letsencrypt, it requires me to put a file with specifc filename and text for the content of the file in /webroot/.well-known/acme-challenge/specificFileName. I have not succeed with this yet. I tried just putting in the folder structure of my container, but this doesn’t seem to work. I tried creating a UDPage with that name and the -content set to just the required text, but that also didn’t work.

I’ve considered revisting the nginx route again, but the way I’ve seen it done is via reverse-proxy, but I’m not sure how this would work with UD serving the http and https (which seems necessary for Azure AD logins). This is a similar problem to just using Azure Web Apps for Containers.

I wonder if it would be possible to specify the redirect url to use https even if we don’t provide a cert to Start-UDDashboard if you’re using a platform like nginx or Web App for Containers…

It might be possible to expose that via UD. When configuring the authentication you set the relative redirect URL (just the /signin-oidc part) and not the full URL. I wonder what would happen if we passed a full URL in there.

Pass in to which part? When I set the redirect URL (in Azure) you have to specify the full URL, and only localhost is allowed to have http instead of https.

In side the actual ASP.NET Core authentication configuration code, you pass in a URL. It’s currently not exposed through the UD cmdlets. I would have to add a new parameter that allowed you to ovverride the URL and I’m not 100% sure that would even do the trick.

Currently, the URL is just set to /signin-oidc but we could try to allow you to set it to the full path of your URL like http://mysite.com/signin-oidc.

I could throw together a special build with that option if you want to try it out.