ADFS Environment Buildup with WCF Utilization – Part 2

In Part 2 we will continue configuring the Identity server starting with installing the Active Directory Domain Services role.

 

Active Directory Domain Services

Begin by opening the Server Manager panel if it is not already. Click on Manage -> Add Roles and Features.

Continue through the wizard until you get to the role selection window and select the Active Directory Domain Services role shown below.

ADDS role selection

Add the additional features that automatically pop up and click “Next”. Continue clicking next until you reach the “Install” page, select the “Restart the Destination server automatically if required” check box, and click “Install”.

 

Static IP

Before continuing configure your Identity Server with a static IPv4 address, and disable IPv6. Since I am on a local network, my static IP is an internal IP only, but this is sufficient for this tutorial.

 

DNS Server and Domain Controller

 

The next things we are going to do are to, promote the identity server to a domain controller, install the DNS Server role onto the identity server, and to create a forest on the DNS Server with forward and reverse lookup zones for our local domain that we will be using for this tutorial. This next step is one good reason to use Virtual Machines if you are performing these configurations strictly as a learning exercise since you would have to have a dedicated domain if the machines were not on a private network.

Start by clicking the notification icon that has appeared since ADDS was added, shown below.

Promote domian controller notification

Next click the “Promote this server to a domain controller” link in the notifications drop down.

promote to DC link

In the wizard that comes up select the “Add a new forest” radio button shown below. Then type in the domain that you will be using.

add new forest domain name

Click next, then select the forest functional levels you want. I leave these at Server 2012 since I don’t plan on interacting with older DNS servers. Then enter a password for the DSRM, I use the admin password for this so it’s easy to remember for the demo but you will likely want a unique password for a production system.

Add new forest

Click “Next”. You will be warned about DNS Delegation options. For this demo on a local network this is not important, for a production environment, creating this delegation should be your next step.

Delegation to parent DNS server

Click OK and Next. Then on the next page click Install. Wait till the installation has finished to proceed.

Once the Identity server has completed it will then be a Domain Controller for martialdeveloper.local, and have the DNS Server role installed and integrated with Active Directory for the domain we created.

Application server IIS

While you are waiting for the Identity server to finish this installation you can start installing IIS on the Application server. Refer back to Part 1 of this series of articles if you forgot how to do this.

 

Configure Active Directory

We will continue by creating Organizational Units in Active Directory. We will be doing this in PowerShell. Please see Stefan Severin’s blog in the references section for the source of these commands. I am very happy to have found them on his blog!

Start by running Powershell ISE in administrative mode, and setting the execution policy to RemoteSigned.

Set-ExecutionPolicy RemoteSigned

Now run the following script to set the Organizational Units. Making sure to replace the first line with one appropriate for the domain you are using.

$domain = "dc=martialdeveloper,dc=local"; 
$ouAdmin = "ou=Adfs Administration"; 
$ouServiceAccounts = "ou=Service Accounts"; 
$ldapConnection = [ADSI] "LDAP://$domain"; 
$newAdminOu = $ldapConnection.Create("OrganizationalUnit", $ouAdmin); 
$newAdminOu.SetInfo(); 
Set-ADOrganizationalUnit "$ouAdmin,$domain" -ProtectedFromAccidentalDeletion $True; 
$ouAdminPath = [ADSI]($newAdminOu.path) 
$newAccountOu = $ouAdminPath.Create("OrganizationalUnit", $ouServiceAccounts); 
$newAccountOu.SetInfo(); 
Set-ADOrganizationalUnit "$ouServiceAccounts,$ouAdmin,$domain" -ProtectedFromAccidentalDeletion $True;

Now create the service account for the ADFS farm. Make sure to enter your domain specifics on line 4. Also, since this is a domain controller the strong password requirements are enabled, so get creative unless you want to have to recreate the account a few times when it fails on the password strength.

$dnsRoot = (Get-ADDomain).dnsroot 
$pwd = read-host "Enter strong password" -AsSecureString 
$upn = "SVC-ADFS" + "@" + $dnsRoot 
New-ADUser –Name "SVC-ADFS" –SamAccountName SVC-ADFS –DisplayName SVC-ADFS -Description "Service account for ADFS farm" -userprincipalname $upn -Path "OU=Service Accounts,OU=ADFS Administration,DC=martialdeveloper,DC=local" –Enabled $true –ChangePasswordAtLogon $False -PasswordNeverExpires $true -AccountPassword $pwd

Configure the SPN (Service Principle Name) for the ADFS service account. Making sure to remember to replace the hostname, and domain information for your environment.

setspn -S host/WIN-924FNOTSB0B.martialdeveloper.local martialdeveloper.local\svc-adfs

Now we install the ADFS Feature onto our identity server machine.

Install-WindowsFeature AD-Federation-Services

We now have ADFS installed, our domain is configured, and we have Active Directory setup. When we continue in Part 3, we will begin by configuring our security certificates for ADFS and IIS.

 

References:

As always, please have a look at my references for further information on the topics discussed above.

Adding Additional Domain Controller (Windows Server 2012)

http://blogs.msdn.com/b/stseverin/archive/2012/12/29/deploying-adfs-2-1-on-windows-server-2012-using-powershell.aspx

ADFS Environment Buildup with WCF Utilization – Part 1

Before I get into it, I wanted to give a little back ground about what this series of articles is, and what caused them to be written.

A while back I had a project come up that needed to use some WCF services for data sharing across multiple device types, and multiple domains.  Given that there were going to be potentially dozens of different corporate domains needing to access these services I thought ADFS or Active Directory Federation Services would be an ideal fit.

Ultimately we used far fewer of the ADFS features than originally thought but regardless, I struggled so much to understand the whole end to end process of building the servers and hosting up from scratch to deploy my services to, that I decided that I needed to document that learning experience in case any developer in the future who, like me, has to build a custom environment from the ground up needs some guidance.

For this tutorial you will need to have at least two Server 2012 machines to work with. You can accomplish this a number of ways, Hyper-V VMs, VMware VMs, two separate physical boxes, Amazon EC2 Instances, etc.. For this tutorial I will be using a single Server 2012 machine running VMs on Hyper-V, but the steps in this guide can be applied to a number of different computing environments. However, I would suggest using VMs on a private network if you are doing this strictly as a learning exercise. In later steps we will have to promote the Identity server to a Domain Controller.

In this tutorial I will be providing a concrete example of creating and configuring a custom application domain and implementing an ADFS server to handle token distribution.

I’m not entirely sure how many parts this series of articles will contain as there is a substantial amount of work and understanding involved here.

 

Before We Begin

Before we can get started, we need to have our first two machines up and running. Creating the VMs that you will be using or building the physical boxes is an exercise for the reader since there are so many ways of going about this.

Okay, so go ahead, get your machines set up, I’ll wait… done yet? No… Now? Okay good! Let’s move on!

 

First Steps

Our first several tasks are going to involve configuring the Identity server for all the various tasks it will be performing in the near future.  The Application server has much less configuration required but we will get to that later.

We are going to start by installing the IIS Role on the identity server. Log into your identity machine, the Server Manager panel should launch automatically. On the Server Manager panel click Manage->Add Roles and Features.

Add Roles

When the Roles and Features wizard comes up, you can click “Next” through the first three screens until you come to the roles selection screen shown below.

IIS role selection

Check the “Web Server (IIS)” box. There will be an automatic pop up asking to install the IIS management tools with the IIS role. Click the “Add Features” button shown below.

Add Feature confirmation

Then click “Next”. You will now be presented with the “Features Selection” screen. Strictly speaking, nothing should be absolutely necessary on this page but I like to add a few things as a personal preference, mostly for backwards compatibility. The three additional options I select are shown below.

Features selection

The HTTP Activation feature will require additional dependencies. Once your features are selected, click “Next” twice.

Now you’re presented with the Role Services selection window. A lot of the choices here are going to be based on your needs, but I have a set of capabilities that I like or need in most IIS installations that I will show below in the next three images.

IIS services 1 IIS Services 2 IIS Services 3

Most of the selections I make here are not strictly necessary but the two categories you need to think about the most are the Security and Logging options.  Additional Security services will allow you the freedom of choosing to authenticate your WCF services/users in more ways, and the additional logging options are extremely handy when you’re getting a very generic authentication failure error message and can’t figure out why.

Now click “Next” and on the following page make sure to select the automatic restart check box as shown below.

Restart and install

Then click “Install”. A progress bar screen will be displayed, and the server will automatically restart during the installation process if necessary.

In Part 2 we will continue configuring the Identity server with the additional roles and services that it needs to act as an identity server, starting with ADDS(Active Directory Domain Services).

Now that you have been through the process of adding a Role, the next section will not have as much detail about how to do this, unless an important configuration needs to be pointed out during the role installation.

UDP Discovery Tutorial – Part 2

In Part 1 of this article I showed how one might use UDP datagrams to discover a client or server on a connected system over an IPv4 network. In Part 2 I am going to add a subsequent TCP connection and briefly explain how it is done.

 

Now we add a TCP connection.

There is more than one way to approach adding a TCP connection to this example.  One of the simpler to understand approaches would be to use UDP to broadcast the listener’s IP back to the broadcaster after the listener received the broadcaster’s IP, and then create a TCP connection between the two specific IPs.

I am not using the above described method however. It seems to me to be a more usable approach to have the broadcaster asynchronously wait for an incoming TCP connection from any source, and once the connection is made authentication can be performed, but as with Part 1, I leave authentication and error handling up to the reader to implement.

Since we are using an asynchronous model for the TCP connection and communications, the pattern that all operations will follow is:

  1. Operation
  2. Callback
  3. Wait on Callback

We will also be using custom events to implement our waiting operations. These are created on lines 28 of the UDPBroacaster project and lines 27-29 of the UDPListener project.

 

Resolve the TCP address to an Endpoint

The first step we perform here is to resolve the TCP address that we are using to an endpoint object for the TCP client object to initialize itself with.

For the listener this is done using the IP received in the UDP datagram:

IPEndPoint remoteEP = new IPEndPoint(tcpAddress, tcpPort);

For the broadcaster this is done using it’s own host IP since we are accepting connections from any other address.

IPEndPoint localEndPoint = new IPEndPoint(localIP, tcpPort);

 

Connect to the Broadcaster

Once we have the endpoints we now attempt a connection to the UDPBroadcast application from the UDPListener application:

            // Connect to the remote endpoint
            client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();  // Without these waits other processing could continue
            listView.Items.Add("TCP Connection Established with UDPBroadcaster");

 

Asynchronously wait for connection

Now we listen for an incoming connection request from anyone within the UDPBroadcast application:

            // Bind the socket to the local endpoint and listen for incoming connections
            //  This logic will parrot back any message received
            listener.Bind(localEndPoint);
            listener.Listen(100);

            // Start an asynchronous socket to listen for connections
            listener.BeginAccept(
                new AsyncCallback(AcceptCallback),
                listener);

            // Wait until a connection is made before continuing
            allDone.WaitOne();
            listView.Items.Add("TCP Connection has been Established, and message received and returned");

The above listening logic for the UDPBroadcast application will asynchronously listen for a TCP connection, and once established, will wait for a message, read the message and return the same message back to the sender.  You can see all the logic for the above within the AcceptCallback() method which you can view by downloading the example projects for this tutorial.

 

Send some test data

Now that we have a connection established, we can send some data to make sure everything is connected up correctly.  We send a test message from within the UDPListener application:

            // Send test data to the remote device
            Send(client, "Hello, this is UDPListener!<EOF>");
            sendDone.WaitOne();
            listView.Items.Add("Message sent to UDPBroadcast");

In a real application this initial message would likely be where you authenticate the connection between the two applications.

 

Wait for responce

Since the UDPBroadcast application is designed to parrot back any message it receives we can immediately wait for a response within the UDPListener application:

            // Receive the response from the remote device
            Receive(client);
            receiveDone.WaitOne();
            listView.Items.Add("Received the following responce from UDPBroadcast: "+response);

 

Close the Connection

Now that we have connected, sent, and received back data from the UDPBroadcast application we can close the TCP connection and release the socket:

            // Release the socket
            client.Shutdown(SocketShutdown.Both);
            client.Close();
            listView.Items.Add("Connection to UDPBroadcast application has been closed.");

 

Final Comments

The above is a very basic example, and as mentioned before error handling and proper authentication is necessary for using this in any real application.  Much of the described logic is encapsulated within the callback methods that can be viewed by downloading the completed example projects linked at the bottom of this article.

I hope this has been helpful to those that have come here to read it. And as always if you have suggestions for improvements to this article, or comments about anything that I’ve done wrong, please leave a comment below.

UDPListenerPart2.zip

UDPBroadcasterPart2.zip

 

References:

As always please refer to my references for further detail.  Much of the code has been compiled from the linked references. For the UDP references see Part 1 of this series.

https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx