<CharlieDigital/> Programming, Politics, and uhh…pineapples

18Feb/170

.NET Core MVC on Azure Container and Registry Service

Posted by Charles Chen

I've recently been playing around with .NET Core MVC and trying to get it running on Azure Container Service (ACS).

Why .NET Core?  Because you'll be able to run those containers on Linux environments, which will generally be lower cost.

It has been quite challenging as there is quite a bit of documentation out there and some of it is out of date already (I certainly expect this to be out of date as we march towards release versions) due to the pace of change with Docker, Docker on Windows, Azure, and the Azure CLI tools.  There are some tutorials which show you how to do it via VSTS and some that seem to show VS2017 tooling for deployment (I sure hope its easier...); I have not been able to activate any tooling support for Docker in VS2015.

Some of the newer capabilities like managing Azure Container Registries (ACR) is only available in CLI 2.0 preview. For example, one would think that once you've created a container registry in Azure, you'd easily be able to see a listing of images you have registered in the Azure dashboard; not so!  The images can seemingly only be seen via the CLI 2.0 commands for now.

There are also multiple ways to take advantage of containers in Azure, but we'll walk through the easiest way using "Web App on Linux" to handle most of the Docker configuration.

Before you get started, you'll need the following:

Now be warned that Docker for Windows runs on HyperV while Docker Toolbox uses VirtualBox.  If you run VMWare locally on your workstation, you won't be able to have HyperV enabled so you've got to settle for Docker Toolbox.  This walkthrough assumes you're using Docker Toolbox, but I assume there's not too much deviation.

For this walkthrough, we're going to focus on the ACR/ACS side of things so we're going to leave the .NET Core side just a basic site.  Follow the instructions here to create a .NET Core web application.

Once you've got that set up and compiled, we need to add one file to the mix: the Dockerfile.  At the root of your web project, add a file named "Dockerfile":

My file contents, based off of this Stormpath tutorial, look like so:

FROM microsoft/dotnet:1.0-sdk-projectjson
COPY . /app
WORKDIR /app
 
RUN ["dotnet", "restore"]
RUN ["dotnet", "build"]
 
EXPOSE 5000/tcp
ENV ASPNETCORE_URLS http://*:5000
 
ENTRYPOINT ["dotnet", "run"]

Nate Barbettini has a good description of what each of the lines means.  Pay attention to the 5000; when we move this into Azure, we'll want to change this to port 80.

For production environments, you'll want to revisit this for sure and build an optimized image using Steve Lasker's walkthrough (I have not tried it yet!) as it will yield a significantly smaller image.  The base image size for the dotnet image is 542MB.  The final size of my basic web application image is a whopping 683MB!

Now if you are using Docker Toolbox, you need to click on the Docker Quickstart Terminal icon which should be on your desktop.  This launches the terminal that we'll be using to:

  • Build the image
  • Tag the image
  • Upload to Azure

We're going to follow along with Barbettini's tutorial.  From the Docker Terminal (terminal), change directories into your .NET application directory (where the Dockerfile was created) and build the image:

docker build -t mywebapp:latest .

This builds a Docker "repository" with the name "mywebapp" and "tag" value of "latest".  Important: note the trailing "." which indicates "from the current directory".

While not strictly necessary, I would recommend running it at this point locally to make sure that it actually works.   Again, we follow along with Barbettini's tutorial and run:

docker run -d -p 8080:5000 -t mywebapp:latest

The application should load at the IP address assigned to the Docker virtual machine and not necessarily localhost.  To see and manage the running instance, you can use the Kitematic application that was installed with Docker Toolbox.  It will generate a random name for the running container and show up on the left hand side.

Hopefully, you've got it running and you've confirmed that it works.  While you're in Kitematic, terminate the container as we're going to now prep it for Azure.  For Azure Web App on Linux (WAL), we will need to map the port directly to 80 (I'm sure there's a way to instruct WAL to map it at runtime, but I haven't figured that out yet).  So update your Dockerfile and replace 5000 with 80.

Now we're going to remove the previous image before we compile a new one.  From the terminal, type:

docker images

This will list the images we have locally. Then:

docker rmi mywebapp:latest

Verify that the image has been removed.  Now we run the build command again and it's time to move onto Azure.

Our first step is to create a private ACR where we can store our image to be used in Azure.  Log into the portal and type in "registry" in the search to find it:

Add a new registry and configure the settings:

I recommend creating a new resource group so that you can more easily delete all of the artifacts later.  Also note to enable "Admin user".  The registry should take a few moments to complete provisioning, but once it's done, go back to the Azure Container Registry to find your newly created registry and select it. Click on the Access key tab and grab the Username and Password:

Next, click on the Quick start tab.  This tab provides the customized commands that we'll need to access our ACR from our local Docker terminal.

Run the following command from the terminal:

docker login mywebappreg-innovocommerce.azurecr.io

The "mywebappreg" will be whatever name you gave to your ACR registry and the "innovocommerce" will be your Azure domain.  This is where you'll need the Username and Password from above.  Next, we're going to tag or rename the image we built earlier:

docker tag mywebapp mywebappreg-innovocommerce.azurecr.io/mywebapp

And finally, we're going to push it into the repository:

docker push mywebappreg-innovocommerce.azurecr.io/mywebapp

This will move the image into your repository -- though there's no way to actually see it in there without the CLI 2.0 preview.  The command should be:

az acr repository list -n mywebappreg -o json

(You'll need to log in first!  Use az login and follow the instructions)

Now we're ready to create our Docker container instance!  You have two options at this point: use the actual Azure Container Service (ACS) OR use Web App on Linux (WAL).  We'll go the WAL route since it's significantly easier!  From the search bar, type "web app" and you should see the Web App On Linux option:

Now we configure the web app:

Here, enter:

  • Your App name for the desired external URL
  • Select your existing registry (again, for easier cleanup later!)
  • And click the Configure container option
  • Select Private registry for the Image source
  • Now enter the tag of the image we pushed earlier: mywebappreg-innovocommerce.azurecr.io/mywebapp:latest
  • Enter the URL of the ACR we created: https://mywebappreg-innovocommerce.azurecr.io
  • Enter the login name and password for the admin user you used to log into the terminal.
  • Leave Startup Command blank (note to Microsoft: inconsistent casing!); I suppose this may be where you could potentially map the ports (maybe?)

If everything works out, you'll be able to click OK and it will go off and provision your container!

To test it out, you can try hitting your site.  As per my example, that would be http://mywebapp5542.azurewebsites.net.  Be patient as it may take a bit of time for the site to come on line.  Remember that this isn't an optimized image.

Next time, we'll explore how to achieve the same result with ACS and maybe optimizing the image for release!

Filed under: .Net, Azure No Comments
1Jun/16Off

Adventures in Single-Sign-On: SharePoint Login Via Office 365

Posted by Charles Chen

If you are still working with on-premise SharePoint 2010/2013 or you application only supports SAML 1.1 but you'd like to leverage your new and shiny Office 365 accounts for single-sign-on, you can achieve this relatively painlessly by using Windows Azure ACS as a federation provider (FP).  It's possible to use Office 365 (Azure AD) directly as your identity provider (IdP), but for SharePoint 2010, this involves writing custom code since SharePoint 2010 can't consume SAML 2.0 tokens without custom code (only SAML 1.1 via configuration).

The overall flow for the scenario is diagrammed below:

Using Windows Azure ACS as a Federation Provider for Azure AD

Using Windows Azure ACS as a Federation Provider for Azure AD

In this scenario, the trust relationship from SharePoint is only to the FP (Azure ACS) which acts as a proxy for the trust to the IdP (Azure AD).  Azure AD contains the actual credentials, but we proxy those credentials through ACS to take advantage of the SAML 2.0 -> SAML 1.1 translation without writing code (otherwise, it would be possible to directly establish trust to Azure AD or through AD FS).  When the user accesses a protected resource in SharePoint, the user is redirected first to the FP which then redirects to the IdP and proxies that response via a series of redirects to the relying party (RP), SharePoint.

The first step is to create an Azure ACS namespace.  You'll need your ACS namespace URL, which should look like: https://{NAMESPACE}.accesscontrol.windows.net

Next, in Azure AD, create a new application which will allow your ACS to use Azure AD as an IdP.  On the APPLICATIONS tab, click ADD at the bottom to add a new application.  Enter a descriptive name for the application (note: you may want a more "friendly" name -- see last picture):

add-acs-application

Then enter the following for the SIGN-ON URL and APP ID URI:

ad-properties

Before leaving the Azure Portal, click on the VIEW ENDPOINTS button at the bottom of the dashboard and copy the URL for the FEDERATION METADATA DOCUMENT:azure-ad-endpoints

Now hop back over to Azure ACS management and add a new identity provider.  Select WS-Federation identity provider and on the next screen enter a descriptive name and paste the URL into the field:

acs-setup-1

Once you've set up the IdP, the next step is to set up the relying party (RP).  The key is to get the following settings correct:

acs-setup-2

In this example, I'm just using my local development environment as an example, but you must specify the _trust URL and explicitly select SAML 1.1 from the Token format dropdown.  Additionally, uncheck Windows Live ID under Identity providers so that only the one configured previously remains checked.

Finally, on this screen, you will need to specify a certificate to use for signing.  Under Token singing, select Use a dedicated certificate and then either use an existing valid X.509 certificate or create one for testing purposes.

Create the certificate using the following command:

MakeCert.exe -r -pe -n "CN={ACS_NAMESPACE}.accesscontrol.windows.net" -sky exchange -ss my -len 2048 -e 06/01/2017

You will need to export the certificate from the certificate store with the private key.  So WIN+R and type in mmc.exe.  From the MMC, click File and then Add or Remove Snap-ins.  Select the Certificates snap-in and click OK.  Locate the certificate and export it with the private key.  While you're here, export it again without the private key; you will need this certificate when setting up the authentication provider in SharePoint.

Back in the ACS management app, upload the first certificate that was exported and enter the password.  An important note is that ACS will always append a "/" after your realm; we will need to make sure what when we register the authentication provider, we include this in the login URL.

Before leaving the ACS management app for good, we need to update the rule group to pass through the claims.  On the left hand side, click on Rule groups and select the default rule group created for our RP.  Now click Generate to create the default rule set.

One thing I discovered through trial and error (mostly error) is that Azure AD does not seem to be providing a value for the emailaddress claim which we will be using later (you don't technically have to use this as the identifying claim, but I did in SharePoint before discovering that this causes an error).  So we'll remap the "name" claim to "emailaddress".  Click on the name claim  (http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name) and select the emailaddress claim type (http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress) as the output claim type.

Now back in the SharePoint environment, we'll now use the certificate exported without the private key to create a new trusted root authority for SharePoint and create and register the identity provider.  Fire up a management shell and enter the following commands:

$certificate = new-object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\temp\cert-no-private-key.cer")
new-sptrustedrootauthority -name "ACS Token Signing Certificate" -Certificate $certificate
$cm0 = New-SPClaimTypeMapping "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -IncomingClaimTypeDisplayName "EmailAddress" -SameAsIncoming
$loginUrl = "https://{ACSNAMESPACE}.accesscontrol.windows.net/v2/wsfederation?wa=wsignin1.0&wtrealm=https://sso.dev.local/&redirect=false"
$realm = "https://sso.dev.local/"
$issuer = New-SPTrustedIdentityTokenIssuer -Name "ACS" -Description "ACS" -Realm $realm -ImportTrustCertificate $certificate -ClaimsMappings $cm0 -SignInUrl $loginUrl -IdentifierClaim $cm0.InputClaimType

And finally, from SharePoint Central Admin, we can now add the "ACS" authentication provider:

acs-identity-provider

The name that we gave earlier to the application in Azure AD can now also be configured to display in the app drawer of Office 365:

o365-apps

Filed under: Azure, SharePoint, SSO No Comments