Getting Up-to-Speed with WS-Federation and WS-Trust

09.04.2012 12:58 by kbeckman | Comments

As part of a recent client request, I’ve been asked to provide a list of resources that an organization can use to become familiar with the technologies and protocols behind enterprise Single Sign-On (SSO) and Federated Identity. Single Sign-On between enterprises is a difficult topic, especially when you get to scenarios beyond the initial user authentication. Trust me, there’s a lot more to think about organizationally than just accepting authenticated users from other security domains. The topic of Federated Identity forces organizations to think of users in terms of a global identity rather than a single account in some enterprise application. Users from the local security domain may or may not be treated differently than users from trusted partners. Application authorization rules may differ based on where your user actually authenticated…

 

The protocols at the core of enterprise SSO are WS-Federation and WS-Trust. At a high-level, WS-Federation defines the transport mechanism for security tokens and WS-Trust defines the procedures for signing, encrypting, validating and renewing authentication tokens. Another popular protocol is SAML 2.0 / SAML-P. [Sorry for the Wikipedia links… I have a better list of resources shortly.] Without getting into the details, there are a lot of functional similarities between WS-Fed and SAML-P… However, the differences are painful enough that we’re going to leave the SAML story for another day (or hopefully never).

 

Microsoft’s implementation of WS-Federation comes in the form of Windows Identity Foundation (WIF) – a subset of the .NET Framework that contains the types and classes for managing identity. Once a standalone extension to the .NET Framework, WIF is now included in the mscorlib. Below are some valuable resources to help you get started with WS-Federation, WS-Trust and WIF.

 

For Business Folks [and Developers Before They Start Developing]…

  • Understanding WS-Federation – This is an MSDN article from back in 2007 (pre-WIF) that describes WS-Federation and it’s sub-protocols (WS-Trust, WS-Security, WS-SecurityPolicy). Brace yourself… The article leads off with a copyright notice and never really recovers.
  • A Guide to Claims-Based Identity and Access Control, 2nd Edition – In my opinion, this is the best resource for explaining SSO and Federated Identity across enterprises. With each chapter, the authors setup an enterprise scenario and explain the interactions required by participating organizations to accomplish SSO. More importantly though, this book goes into detail to explain the business problems solved by SSO implementations. Developers will get a lot from this too as it touches on all of the Microsoft technology offerings that are either necessary or helpful in pulling off SSO – ASP.NET, WIF, Active Directory Federation Services 2.0, and Windows Azure Access Control Service.

For Developers…

 

For ‘Only the Lonely’

If you haven’t gotten your fill from the resources above, you can always take a look at the official OASIS protocol specs. Although I don’t advise this unless you’re working on your own framework or plug-in, etc.

Just Go Ahead and Write the Test

07.05.2012 23:37 by kbeckman | Comments

Recently, I’ve found myself in a couple of rework or debug situations where I’ve really wished that I had taken a few extra minutes and written a test or two to prove the code in question actually worked at one time… Both situations were outside of what I would consider the “normal” day-to-day unit testing scenarios where I’m covering typical model or controller logic. One situation involved dynamic routes created by OmniAuth and the other involved a local Git submodule for a gem I’m working on.

 

Adding the route tests was an easy fix, but it took me a couple days worth of recommitting the same submodule pointer updates in our base repo before I finally got sick enough of re-doing it. It helped to finally figure out why it kept happening too… One of the other devs on the team had re-cloned the project repo and forgot to do the submodule init/update steps. Every time I would commit, I would update the submodule commit pointer. Every time he would commit, it would roll the commit pointer back to a previous version. One RSpec test put an end to all of the commit games…

 

require 'spec_helper'

describe "Git Development Submodule" do

  it 'should have the latest commit id' do
    submodule_status = `git submodule status`
    error_msg        = 'Solution: git submodule update && git submodule init"

    # Ensuring the [git submodule status] command actually produces a result...
    # TeamCity tests are run under a build agent where source code is copied to rather than updated/fetched in a git
    # repo. This is a local dev machine test only...
    if status_msg.present?
      status_msg.should include '24a1c1299....', error_msg
    end
  end

end
  • Just shell-out using the git submodule statuscommand which returns the current submodule commit ID.
  • Notice the check for a status message before checking the commit ID. Depending on your build server configuration, you may not get a value for this when running in a CI scenario…

VirtualBox: Configuring Static IPs for VMs

06.14.2012 00:57 by kbeckman | Comments

Late last year, I wrote about a hack I came up with for configuring a VirtualBox guest OS with DHCP and ensuring it always got the same IP address. After a new project and some new insight, I’ve figured out a new way that deprecates all of the information in that post. Under that configuration, I assumed that the only way to get a static IP address for a Windows guest OS was to join it to the corporate domain – I was wrong. In the steps that follow, I’ll explain how to set up VirtualBox networking and the network settings for Windows and Ubuntu guests to support static IPs on your VMs. This will make it possible for you to connect from VM-to-VM (provided they’re both running) and for your host OS (in this case Mac OSX) to connect to each VM via static IP.

 

Step 1: VirtualBox Network Settings

To enable static IP addresses on your VirtualBox VMs, you’ll first need to setup a Host-Only network. The host-only network is a virtual network provided by VirtualBox that is visible only to the Host OS and its virtual machines. VirtualBox should setup a default host-only network during installation, but if it doesn’t you can add one pretty easily. Go to VirtualBox’s application menu and select Preferences – Network. Here you’ll be able to add a host-only network if it doesn’t exist… If desired, you can also configure multiple host-only networks allowing you to create various scenarios where VMs are networked together or fenced-off from each other.

 

virtualbox networking

VirtualBox Host-Only Networks

 

Below are my VirtualBox network settings. As you’ll notice, I’ve enabled the DHCP server on the host-only network albeit unnecessary. I just wanted to show that you can have it enabled and still assign your VMs static IP addresses.

 

host-only adapter          host-only dhcp

VirtualBox Host-Only Network Adapter and DHCP Server Settings

 

Step 2: VirtualBox VM Network Adapter Settings

In this scenario, your VMs will need two network adapters – a NAT adapter for Internet connectivity; and a Host-Only adapter for the network we configured in Step 1. When you create your new VM settings, VirtualBox should add a NAT adapter by default so you shouldn’t have to do anything here.

 

vm nat adapter

Virtual Machine Settings: NAT Network Adapter

 

Enable the host-only adapter by clicking the Enable Network Adapter checkbox on the Adapter 2 tab. Select Host-Only Adapter from the Attached To combo box and select the host-only network you created in Step 1 in the Name combo box. If you only have one host-only network, this will already be selected… Please note this is a single VM configuration. You’ll have to add the host-only adapter to all of your participating VMs.

 

vm host-only adapter

Virtual Machine Settings: Host-Only Network Adapter

 

Step 3 (Windows): Static IP Configuration (Host-Only Network)

Setting up a static IP on a Windows machine is fairly straightforward as the IPV4 settings dialog should be familiar to almost everyone… Below I’ve configured the Default Gateway and Preferred DNS Server boxes to contain the host-only network adapter address configured in Step 1 (192.168.56.1). I’ve assigned a static IP similar to the default gateway incrementing the address’s last number by one. There is no configuration necessary for the NAT network adapter. Below you’ll also notice a screen shot of my Windows network properties. For reference purposes only, I renamed the machine’s networks to reflect the names of the VirtualBox network adapters.

 

windows ip settings          windows network settings

Windows IPV4 Configuration Settings

 

Step 3 (Ubuntu): Static IP Configuration (Host-Only Network)

Configuring a static IP in Ubuntu (I’m using the latest version available, 12.04) is just as straightforward as the Windows configuration. Again, you’ll only need to configure the host-only network adapter – the settings are exactly the same as they were for the Windows machine except for the IP address. Both the Default Gateway and Preferred DNS Server should be set to the host-only network adapter address configured in Step 1 (192.168.56.1). Just choose your static IP and you’re finished. As before, for reference purposes I’ve renamed each of my Ubuntu networks to match the VirtualBox network adapter name.

 

ubuntu ipv4 settings          ubuntu network settings

Ubuntu IPV4 Configuration Settings

 

All in all, the static IP configuration is really easy. Nothing more to say on this topic…

WHERE Clause Functions: A Word of Caution…

04.23.2012 22:32 by kbeckman | Comments

A little more than a year ago, I wrote a post explaining a way of refactoring stored procedures to reduce the number of similar procedures that differed only by the logic included in the WHERE clause…

 

Here’s my exact quote:

“Your codebase has a glut of repeated stored procedure logic for “get” or SELECT-based operations. Table JOINS, stored procedure parameters (for row filtering) and return types are similar among a focused set of stored procedures. The focused stored procedure group resembles the following pattern: GetEntityById, GetEntitiesByParentId, GetEntityByExactName, GetEntitiesByPartialName, GetEntityBySomeOtherParameterCombo.

Use the T-SQL COALESCE function in the procedure’s WHERE clause logic to implement optional parameters and combine the many similar, individual procedures into a single procedure with functionality for multiple input parameter combinations that yield a single return type.”

 

If implemented properly, the approach I detailed could significantly reduce the number of similar SELECT stored procedures in the database making your life easier as a developer having fewer procedures to maintain. I recently discussed this approach with our Head DBA and he had some reservations claiming that function usage in WHERE clauses could lead to performance issues. With a little more insight, I wanted to take an opportunity to evaluate my original procedure example and refactor it if I could find a better way.

 

Optimization Guidelines for WHERE Clauses

After an hour or so of research, AdventureWorks testing and several articles later (see Resources section at the end of this post), I’ve come up with a few guidelines to help squeeze the best performance out of your procedure execution – at least as far as your WHERE clause is concerned.

  • Know How to Read Your Execution Plan – There’s probably no better tool for performance feedback and optimization than SQL Server’s query execution plan viewer. This will present a visual representation of SQL Server’s query execution operations along with valuable metrics such as execution time, CPU cost, I/O cost, number of rows processed, etc. Seek out and destroy/minimize all Table or Index Scans!
  • Make Your WHERE Clause Columns Immediately Visible to SQL’s Query Optimizer – In other words, don’t bury your filter columns inside a function. Instead call-out the column followed by whatever function you need to complete the expression enabling the Query Optimizer to identify and use any indexes related to the column. Here’s a couple of examples: 
    • DO – WHERE Person.LastName LIKE ‘Beck%’
    • DON’T – WHERE SUBSTRING(Person.LastName, 5) = ‘Beck’
    • DO – WHERE Person.DOB > DATEADD(yyyy, –21, GETDATE())
    • DON’T – WHERE DATEDIFF(yyyy, Person.DOB, GETDATE()) > 21
  • Avoid Nested AND/OR Logic – There may be a creative way to eliminate the use of simple OR chains in your WHERE clauses. If there is, you should use it. While this isn’t a hard-and-fast rule, it is what I identified in my example procedure as something that could be optimized. By rethinking the expression, I was able to reduce the query cost of an index scan on Address.City. Aside from a performance increase, WHERE clause logic will be easier to read if your expressions are simpler. You should treat nested WHERE clause logic in your T-SQL the same way you should treat nested IF statements in your application code – eliminate it with extreme prejudice.

 

Let’s Review the Original Example

Below is the original stored procedure example in its entirety. According to the three guidelines above, the procedure has already called-out the filter column in the WHERE clause making it immediately visible to the Query Optimizer; I’ve evaluated the execution plan (actual output is below); and I’ve identified an ugly nested OR that can be cleaned up…

-- ==========================================================================================
-- Author:      Keith Beckman
-- Create date: 1/7/2011
-- Description: Selects complete address data based on a variety of input criteria.
-- ==========================================================================================
CREATE PROCEDURE [Person].[GetAddresses]
    @AddressId            INT = NULL
    , @PartialCity        NVARCHAR(30) = NULL
    , @StateProvinceId    INT = NULL
AS
BEGIN
 
    SET NOCOUNT ON;
 
    SELECT TOP 20    
        A.AddressID
        , A.AddressLine1
        , A.City
        , A.PostalCode
        , SP.Name
        , CR.Name
    FROM    Person.Address A
            INNER JOIN Person.StateProvince SP ON SP.StateProvinceID = A.StateProvinceID
            INNER JOIN Person.CountryRegion CR ON CR.CountryRegionCode = SP.CountryRegionCode
    WHERE    A.AddressID        = COALESCE(@AddressId, A.AddressID)
        AND A.StateProvinceID   = COALESCE(@StateProvinceId, A.StateProvinceID)
        AND((@PartialCity IS NULL AND A.City = A.City) OR A.City LIKE '%' + @PartialCity + '%')
END

GO

 

Below is the SQL Server actual query plan results for the following procedure call…

--Get all addresses with a city name like "Birm"...
--Replaces: GetAddressesByCityName
EXECUTE AdventureWorks.Person.GetAddresses 
  @PartialCity = 'Birm'
GO

 

image  image

 

One thing to note, using the AdventureWorks database is a contrived example and due to the database size any optimizations will be unnoticeable to the naked eye. However, when you’re working with extremely large tables in a high traffic DB, minor enhancements like the following can make a big difference. Notice the Index Scan above. At 65% of the entire query cost, this could be a big bottleneck under the right conditions.

 

Let’s Tweak the WHERE Clause

WHERE    A.AddressID       = COALESCE(@AddressId, A.AddressID)
   AND A.StateProvinceID   = COALESCE(@StateProvinceId, A.StateProvinceID)
   AND A.City              LIKE '%' + COALESCE(@PartialCity, A.City) + '%'

 

As I mentioned earlier, all we really needed to do for this query is optimize the WHERE clause filter for the Address.City column. Instead of the nested OR that evaluates whether or not the @PartialCity parameter IS NULL and then builds a LIKE expression, I made the entire check a LIKE expression that was immediately aware of the target column, Address.City. Executing the same procedure call against the optimized procedure produced the execution plan results below.  As you can see from the Clustered Index Scan statistics (previously the most expensive part of the query as defined by Cost %) the Estimated I/O Cost and Estimated CPU Cost figures were reduced dramatically. I didn’t eliminate the Clustered Index scan completely, but it is a significantly less percentage of the overall execution cost. The NonClustered Index Seek operation increased by a factor of 6, but since this is always a faster operation than a Scan, it’s more efficient for the overall query execution.

image   image

 

In Closing

There’s always room for refactoring in every line of code you write. Sometimes it will be a year or more before your original code becomes a problem. Or it could take that long for you to circle back around to it… Check your ego at the door and question everything. No matter how good you think you are or how good you really are, you’ve written code that can be improved for both performance and readability.

 

Resources

The Cost of Function Use in a WHERE Clause

Avoid SQL Server Functions in the Where Clause for Performance

Execution Plan Basics

DateTime DSL: Finishing Out the DSL

01.25.2012 09:03 by kbeckman | Comments

C4SC DSL Series Catalog

GitHub Repo

 

Well, Readers… I’m proud to say that the C4SC DateTime DSL is finally complete (as far as this blog series is concerned anyway). Below I detail some changes that I mentioned in my prior post as well as a few that hadn’t thought of at the time. With 170+ unit tests covering the various pieces of DSL functionality, this is finally ready for production! Check out the complete changes in their entirety in my C4SC GitHub Repo.

 

Adding the Week() and Weeks() Methods…

This enhancement was extremely easy considering that the necessary DSL plumbing was already there. Adding the Week() and Weeks() methods simply required multiplying the Day component of the DateTimeComponents instance by 7. I’ll spare you the unit test updates as they don’t look any different than before. They just account for any additional days added or subtracted by Week() or Weeks().

/// <summary>
/// Converts an Int32 to its equivalent DateTimeComponents representation in weeks. 
/// </summary>
/// <param name="weeks">Number of weeks.</param>
/// <returns><see cref="DateTimeComponents"/> composed of the given week parameter.</returns>
public static DateTimeComponents Week(this Int32 weeks)
{
    return weeks.Weeks();
}

/// <summary>
/// Converts an Int32 to its equivalent DateTimeComponents representation in weeks. 
/// </summary>
/// <param name="weeks">Number of weeks.</param>
/// <returns><see cref="DateTimeComponents"/> composed of the given weeks parameter.</returns>
public static DateTimeComponents Weeks(this Int32 weeks)
{
    return new DateTimeComponents(0, 0, weeks * 7, 0, 0, 0);
}

 

Yesterday and Tomorrow…

Implementing the DSL equivalent of Yesterday and Tomorrow is definitely the portion of the DSL that I’m least proud of. The static nature of C# required me to write way more code than I wanted to pull this off. Having a language feature like modules would have made this a trivial exercise as I would have been able to include a globally available set of methods for Yesterday and Tomorrow. Instead, I created a static class for both Yesterday and Tomorrow each with a Date() method that returns the desired DateTime value. A whole class you say? Yeah I know… It was the only way I could think of though to achieve the syntax that I wanted… I guess it’s a small price to pay for better code readability. The DateTimeNowAdapter noise you see below is explained here for those of you just joining in.

/// <summary>
/// DateTime DSL implementation for Yesterday's date.
/// </summary>
public static class Yesterday
{
    private static IDateTimeNowAdapter _nowAdapter = new SystemDateTimeNowAdapter();
    private static readonly object _syncLock = new object();

    /// <summary>
    /// Sets the DSL's IDateTimeNowAdapter. This is the injection point for tests to provide their own adapter
    /// implementation.
    /// </summary>
    /// <param name="adapter"><see cref="IDateTimeNowAdapter"/> implementation.</param>
    internal static void SetDateTimeNowAdapter(IDateTimeNowAdapter adapter)
    {
        lock (_syncLock) { _nowAdapter = adapter; }
    }

    /// <summary>
    /// Yesterday's Date.
    /// </summary>
    /// <returns>Yesterday's date value 24 hours ago.</returns>
    public static DateTime Date()
    {
        return _nowAdapter.DateTimeNow().Date.AddDays(-1);
    }
}

 

Saving the Best For Last… The [Almost] Complete .NET Port of the Rails Date Class

Throughout this series, I’ve commented that the inspiration for this DSL was syntax I encountered in the Ruby language – more specifically the helper methods in the Rails Date class. All of the work up to this point for calculating DateTime covered only a portion of the methods and functionality available in Rails’ Date class. But in the spirit of open source, I wanted to finish this DSL out for anyone besides me who might want to use it.  Instead of providing a set of methods that act upon a semantic model to cache a set of calculations I wanted to make on a DateTime value, I was simply able to add some extension methods to the native .NET DateTime Type. For brevity, only a partial class implementation is below.

 

Anyone who is familiar with the Rails Date class will notice some missing methods… Luckily for me, the functionality in the missing methods is available as part of the native .NET DateTime or String Types and didn’t need to be accounted for here. These are things like to_datetime (DateTime.Parse()), to_formatted_s (String.Format), acts_like_date?, etc. There are also a lot of method aliases that I left out in favor of a single method syntax for a given piece of functionality. For my .NET readers, Ruby aliases are just another name for method delegation where you’d wrap an existing method call with another method with a better or different name.

/// <summary>
/// DateTime extension methods. This class is a .NET partial port of the helper methods in the Rails Date class.
/// </summary>
/// <remarks>
/// http://api.rubyonrails.org/classes/Date.html
/// </remarks>
public static class DateTimeExtensions
{
    private static readonly int[] _q1 = new[] { 1, 2, 3 };
    private static readonly int[] _q2 = new[] { 4, 5, 6 };
    private static readonly int[] _q3 = new[] { 7, 8, 9 };

    /// <summary>
    ///    Resets the time portion of the DateTime to 00:00:00.
    /// </summary>
    /// <param name="dateTime">DateTime evaluation target.</param>
    /// <returns>Given date value at 00:00:00.</returns>
    public static DateTime AtMidnight(this DateTime dateTime)
    {
        return dateTime.AtBeginningOfDay();
    }

    /// <summary>
    ///    Resets the time portion of the DateTime to 00:00:00.
    /// </summary>
    /// <param name="dateTime">DateTime evaluation target.</param>
    /// <returns>Given date value at 00:00:00.</returns>
    public static DateTime AtBeginningOfDay(this DateTime dateTime)
    {
        return dateTime.Date;
    }

    /// <summary>
    ///    Resets the day value to Sunday of the current week at 00:00:00.
    /// </summary>
    /// <param name="dateTime">DateTime evaluation target.</param>
    /// <returns>Sunday of the current week at 00:00:00.</returns>
    public static DateTime AtBeginningOfWeek(this DateTime dateTime)
    {
        return dateTime.AddDays(-(Int32)dateTime.DayOfWeek).AtBeginningOfDay();
    }

    /// <summary>
    ///    Resets the day value to the first of the month at 00:00:00.
    /// </summary>
    /// <param name="dateTime">DateTime evaluation target.</param>
        /// <returns>First day of the month at 00:00:00.</returns>
    public static DateTime AtBeginningOfMonth(this DateTime dateTime)
    {
        return new DateTime(dateTime.Year, dateTime.Month, 1);
    }

    /// <summary>
    ///    Resets the date value to the first day of the quarter at 00:00:00.
    /// </summary>
    /// <param name="dateTime">DateTime evaluation target.</param>
    /// <returns>First day of the quarter at 00:00:00.</returns>
    public static DateTime AtBeginningOfQuarter(this DateTime dateTime)
    {
        return _q1.Contains(dateTime.Month) ? new DateTime(dateTime.Year, 1, 1).AtBeginningOfDay() :
            _q2.Contains(dateTime.Month) ? new DateTime(dateTime.Year, 3, 1).AtBeginningOfDay() :
            _q3.Contains(dateTime.Month) ? new DateTime(dateTime.Year, 7, 1).AtBeginningOfDay() :
                new DateTime(dateTime.Year, 10, 1).AtBeginningOfDay();
    }

    /// <summary>
    ///    Resets the day value to January 1 of the current year at 00:00:00.
    /// </summary>
    /// <param name="dateTime">DateTime evaluation target.</param>
    /// <returns>January 1 of the current year at 00:00:00.</returns>
    public static DateTime AtBeginningOfYear(this DateTime dateTime)
    {
        return new DateTime(dateTime.Year, 1, 1);
    }
}

 

A Quick Moment To Reflect…

This series was a LOT of fun and incredibly educational for me. It allowed me to take my new appreciation for more English-readable code from my recent work with Ruby and open source projects and apply it to a static language in C#. I’ll be taking these new techniques forward with me in future .NET development and I won’t be one to settle with the syntax offered by the .NET Framework or other frameworks. I hope you enjoyed this as much as I did!

 

Comments welcome!