-
To the already initiated claims disciples, the Access Control Service is a multi-tenant Resource STS. The behavior of each STS is determined by simple rules - the rules control how each STS transforms claims.
To those not already initiated in the claims methodology, the previous definition may seem a bit obtuse. If that's the case, then consider a simple scenario:
Background
Let's say you work for a software vendor (Foo) that sells a web application (how about employee payroll management) to businesses. You have an existing on-premise offering and an existing install base. This version of your software integrates with customer identity providers (e.g. Active Directory, Tivoli, etc.).
Customer administrators can allow other employees access to the payroll system - this is driven by group membership (e.g. Domain Users have access). Internally the application uses a set of pre-defined roles, and assigns permissions based on role membership. As an example, consider the following simple model:
Active Directory Group= HR Payroll --> Application Role = Administrator
Application Role = Administrator --> Permission = CreatePayroll
Application Role = Administrator --> Permission = PrintPayrollChecks
...
This approach is known as Role Bases Access Control (RBAC). It's very simple, powerful, and very common.
Given that Foo's existing offering is on-premise it works well. Initial setup requires some basic plumbing with a single on-premise identity provider and a bit of configuration by the application administrator.
The Winds of Change
Some of your existing customers and many prospects are asking for a hosted / cloud version of your payroll application. As your team considers options, it becomes apparent that a good long term approach is to modify the existing on-premise application to be multi-tenant. Modifying a single tenant application to be multi-tenant isn't a joke, but customers are demanding it, so you proceed.
One of the things your team realizes pretty quickly is that the RBAC model in the on-premise application has to change a bit. The core concept of mapping groups to roles to permissions appears to still be viable, but now there are multiple identity providers. Your application now has to be able to differentiate Bar Corporation Groups from Baz Corporation Groups.
Luckily most of the software vendors that sell identity providers have built versions of their identity providers that will expose groups and other identity attributes outside of the corporate LAN. I believe that Microsoft's offering in this area is outstanding (Geneva Server, Geneva Framework, Microsoft Services Connector and the Federation Gateway - see Kim Cameron's blog for fantastic details). Concretely, this means that the hosted, multi-tenant version of your application can federate with lots of different corporate identity providers.
The Access Control Service
There is still a problem, however. You'll have to add quite a bit of code to your application to accept and parse tokens from these identity providers. To top it off, you'll have to make it pretty flexible and configurable. This is where the Access Control Service shines. In a nutshell, it is a service that simplifies interactions with any standards based identity provider, and allows you to define rules that transform Groups to Application Roles to Application Permissions.
To put it another way, your application won't have to directly interact with any identity providers. It can trust tokens from the Access Control Service. The Access Control Service will handle the gory details of decrypting, verifying and parsing tokens, extracting Groups (or other identity attributes) from tokens, and mapping Groups to Application Roles to Permissions. The end result is a single sign-on experience for your customers, and a simplified code base.
Up next - the common interaction model of the Access Control Service & why claims disciples call it a claims transformer.
-
Today we announced the CTP release of .NET Services! For quite a while now, I have been working on this project. It's great to see it announced and to have customers use our services. .NET Services consist of three services: the Service Bus, the Workflow Service, and my personal favorite: The Access Control Service.
My focus has almost exclusively been on the Access Control Service, so expect it to be the main topic of this blog for quite a while. The Service Bus, Workflow Service, and the portals use the Access Control Service so I will likely spend some time on those as well.
In a nutshell, the Access Control Service allows you factor access control code into a manageable collection of rules. Combined with Geneva Server and the Geneva Framework, you can do things like map groups to roles, and roles to permissions.
-
Yesterday we released a new version of BizTalk Services (R12). Over the next few weeks I'll be updating my blog with descriptions of the identity related features we added in this release. For now I'd like to describe one of the most obvious changes to the way you create, view, and manage access control rules.
To explain what these modes do, let me first describe the changes we made. Here are a few of the key concepts:
- Every Identity Service account owns a Security Token Service (STS).
- An STS is composed of one or more scopes.
- A scope contains zero or more access control rules.
- An STS owner can grant another Identity Service account permission to edit the access control rules in a scope
2-4 are new. The messaging (also called relay) service uses these concepts. It has no Identity Service special privileges. It is using the same core features available to everyone else. The Messaging Service owns an STS and it defines a root scope of http://connect.biztalk.net/services/. When you create a new account (newaccount) in the Identity Service, the messaging service creates a new scope http://connect.biztalk.net/services/newaccount. The Messaging Service then grants (newaccount) the permission to edit access control rules in (and only in) that scope. This new account provisioning is done in a provisioning agent that uses our public API.
Newaccount can also create a scope within that scope (like http://connect.biztalk.net/services/newaccount/newestscope). NewAccount can then grant another IdentityService account permission to edit access control rules within that scope.
The behavior here is functionally similar to what an ISV might want (allow one of their customers to define access control rules for their “chunk” of the service).
It is important to note that the access control rules that belong to the scope http://connect.biztalk.net/services/newaccount are owned by the Messaging Service. NewAccount does not own the rules, it has just been granted permission to edit rules within that scope.
When designing the UI we wanted the experience of editing access control rules in a scope owned by another account to be distinct from the experience of editing access control rules in scopes you own. Our first attempt at drawing this ownership boundary is to set the default UI mode to show only the scopes you own. We called the default mode “Basic”. The mode that provides visibility into scopes owned by other accounts is called “Advanced”. In short, if you want to work with the access control rules in the messaging service scope (or the workflow scope), you can switch the mode to “Advanced” (shown below).

In keeping with the traditions of BizTalk Services, we love feedback – let us know what you think…
-
One of the little known features of BizTalk Services is it's support for metadata. There's a sample in the SDK (default path: C:\Program Files\Microsoft BizTalk Services SDK\Samples\Communication\ExploringFeatures\Metadata\MetadataExchange\CS30) that shows you how to listen for incoming metadata requests through the relay. It tracks with the WCF metadata story and is built on WCF extensibility points. In fact, if you open the machine.config file, you will see the policy importers and the WSDL extensions.
The end user experience is quite simple. At some point, you setup the service behavior
<behaviors>
<serviceBehaviors>
<!-- Application Behaviors -->
<behavior name="serviceMetadata">
<serviceMetadata />
</behavior>
</serviceBehaviors>
</behaviors>
Next you define an endpoint - (Notice the binding is the RelayBinding and not the normal metadata binding.)
<endpoint name="MexEndpoint"
contract="IMetadataExchange"
binding="relayBinding"
bindingConfiguration="default"
address="mex" />
That's about all that's required to expose metadata.
Consuming it is just as easy. From a new VS project, all you have to do is right click the project and select "Add Service Reference" (VS 2008).
In the next window, enter the service bus URI (like sb://connect.biztalk.net/services/justinjsmith/Echo) and click Go:
When you click OK, the tooling (think svcutil) will generate the proxy code and config for you. In an empty project, literally the only two lines of code you have to write are:
EchoContractClient client = new EchoContractClient();
Console.WriteLine(client.Echo("hi there"));
-
This week I started a new job at Microsoft - I've moved from Developer and Platform Evangelism to the Connected Systems Division. I'm now a program manager on the BizTalk Services team (http://biztalk.net). It was hard to leave DPE, but this seems like the right opportunity. For those that haven't seen BizTalk.net, it's an incubation project for messaging, security, and workflow services that run at scale in Microsoft's hosted environment.
The week was a whirlwind, and I am having a blast. The team is very agile, and it has the atmosphere of a startup. Truly cool.
-
I just posted a new screencast on Channel 9: http://channel9.msdn.com/Showpost.aspx?postid=386824.
It's purpose is to show off the power of claims and claims transformation, especially in a hosted service like BizTalk Services.
-
The identity provider in BizTalk Services is a way for applications to delegate identity and access control to a hosted service. In other words, an application can use BizTalk Services to answer the all-important question "Who are you and what are you allowed to do?". If you haven't checked it out, I strongly recommend it (http://biztalk.net).
The identity provider can be used without the connectivity service. The calculator sample in the SDK is an example (as of R10, it installs by default in the C:\Program Files\Microsoft BizTalk Services SDK\Samples\AccessControl directory). This entry examines the calculator sample that uses a certificate, and this blog post is not a substitute for reading the readme...
As indicated in the readme, running this sample requires you to login to http://biztalk.net, go to "Manage Access Control", "Rules", and setup a few claims mappings. After you login, click on the following (right hand side):
The Rules link takes you to a page that lets you map input claims to output claims. In the case of the Calculator sample, you are going to map BizTalk.NET usernames to Resource+Operation claims. These Resource+Operation claims are demanded by the calculator service (running on your machine). WCF shields you from quite a bit of the protocol level goo here. The following is an example of what it looks like in the web UI:
There's lots of interesting things going on here. For now, let me just focus on the Output Claim Value field. It's the concatenation of (in this case) the service URL, "#", the service contract name, ".", and the action of the operation:
<Value> ::= <Service Url> "#" <Service Contract Name> "." <Operation Action>
This may sound very scientific, but the reality is that it's simply a matter of a choice made by the ServiceAuthorizationManager derived type that's included in the Calculator sample (available at C:\Program Files\Microsoft BizTalk Services SDK\Samples\AccessControl\CalculatorServiceWithCertificate\FederatedAccessManager). You can change it to be whatever you want (of <Read> or <Write> could have been substituted for contract name + operation action).
After you setup the input and output claim mapping for the calculator service, you have a system like the following:
Step 1: Present identity claims to BizTalk.NET
Step 2: Receive the claims that are mapped to that identity
Step 3: Send those claims to the Calculator Service
Step 4: If the claim (URL+ContractName+Action) is present, the ServiceAuthorizationManager allows the WCF infrastructure to invoke the calculator implementation.
In effect, the calculator service delegates identity and access control to BizTalk Services.
I think that's way cool.
-
A little while ago I ran into an interesting set of errors that may be of interest to you. Consider the following service contract snippet:
[OperationContract]
[WebGet(UriTemplate="foobar/{value}")]
String GetData(String value);
If you add the enableWebScript behavior to an endpoint that is using the WebHttpBinding, you will see this exception when the ServiceHost starts:
System.InvalidOperationException: Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'.
The reason for this error is rooted in the origin of the enableWebScript behavior. One of it's design objectives was to simplify working with the ASP.NET AJAX stack (Javascript proxy, JSON messages, etc). The AJAX stack doesn't have the equivalent of the UriTempalte type. It simply puts parameters in query strings (gets) and constructs entity bodies (posts). This is the default behavior of the WCF stack when the WebGet / WebInvoke annotations do not have a value for UriTemplate. Since any value of UriTemplate would be incompatible with the ASP.NET AJAX stack, we throw when it's present.
If you want JSON messages from a contract and you want to use the UriTemplate niceness, you can change your contract to:
[OperationContract]
[WebGet(UriTemplate="foobar/{value}", ResponseFormat=WebMessageFormat.Json)]
String GetData(String value);
Then, instead of using the enableWebScript behavior, use the WebHttpBehavior. You'll lose compat with the ASP.NET AJAX client stack (and the JS proxy), but you have the URI you are looking for.
The same is true if you are using the WebInvoke attribute and any HTTP method other than POST. The AJAX client stack only knows GET and POST...
-
I'm not prone to publish non-techie topics on this blog, but I can't help this one :). I'm often asked what life is like at Microsoft, and this video pretty much sums it up...
http://on10.net/blogs/tina/Life-At-Microsoft/
-
My friend Vittorio has posted that MySpace will be talking about WCF at Mix 2008 (see it here). This promises to be a good session!
-
I thought it might be mildly interesting to document the lifecycle of a demo. Over the next week or so I have to design, build, and deploy a demo that shows off some of the web-centric features of WCF in the .NET Framework 3.5. First, let me state the constraints:
1) it has to be lightweight - a person in the field or in the community must be able to run it with a bare bones setup (VS only)
2) it has to be "codable" from the ground up in a short period of time w/o much practice
3) it has to show off the new HTTP programming model, Syndication, and JSON messaging.
4) it should also bring to the surface other WCF features like new tooling, flexible configuration options, etc.
5) ideally, a silverlight client consumes the services.
I'm not sure how many parts it will take to blog this. Time will tell.
Since the demo is supposed to be lightweight and it has to be codable, it is going to lack the "real life" aspect. Simplicity and demos and reflecting real world scenarios are often in conflict in demos. Since this is not going to be a keynote, there is no need to dwell on it too long.
With that in mind, I will build an album metadata sharing service. The service just returns information about albums in a store and provides consumers with some ability to create side effects (add, change, or delete an album). Because the demo is supposed to be codable, we will keep the album type definition simple, maybe just a few fields.
There will likely need to be a backing store for the album data, so we have to decide where to store album data. Since DB connections can be annoying to deploy to lots of people, I will opt for an XML File in a VS project.
In regards to project structure, the VS solution will have 2 projects: AlbumService (WCF Service) and AlbumClient (Silverlight app). If we are feeling spunky, we can also build an ASP.NET AJAX app that uses the service.
Now it's time to code. I've found it's important to document any hiccups that occur along the way, and be certain those get communicated to the people that may present the demo in the future. I use a simple MS Word document. In this case, I am using LiveWriter, and posting it to my blog :).
Step 1: Create a VS Solution
Easy enough.
Step 2: Create a WCF Class Library Project
VS 2008 includes some new WCF tooling. You basically go to File->New->Project->WCF->WCF Service Library.
In keeping with the VS Tradition, several files are created for you that have mildly annoying names like IService1, Service1, and some random namespace. Even though the names are a bit annoying, the project will compile and run as is.
So, if one is giving this demo live, you could literally press F5, see the autohost and new WCF client start, and talk to those for as long as you felt compelled. I think the following points are important:
1) the autohost is a dev-only thing. It is all about getting a feedback loop going. It's kindred spirits with Cassini.
2) the autohost also lets you defer the choice of hosting. It may be the case that you aren't sure which host you will use. This autohost model helps you avoid (but doesn't prevent) you from creating frivolous dependencies on a type of host.
3) the test client makes it easy to pass basic data back to the service and check the results. Again, this is about a feedback loop.
4) The App.config created by the project creates 2 endpoints: a wsHttpBinding endpoint and a metadata exchange endpoint. It may be worth talking about how simple it is to setup endpoints that adhere to these complex protocols. It depends on the audience. Some of the more militant RESTafarian sects may well try to light your hair on fire if you bring up WS-*.
5) You can change the config options using a new tool (WCFConfigEditor.exe). You get to that tool by right clicking the App.config file. This only works for the WCF Service library project. If you are trying to edit a config file in a project that was not created from that template, then you can go to the Tools menu, then select WCF Service Configuration Editor. After you do that, subsequet request for the context menu will work.
In part 2, I will run through the code and config changes.
-
Previous posts have talked a bit about PictureServices. Now I'd like to run through what it took to bring PictureServices to the BizTalk Services. I've talked a bit in other posts about BizTalk Services, but it has some interesting and very useful messaging features. For starters, BizTalk Services has an endpoint that can do HTTP transforms on messages. It goes like this:
- MyApp connects to BizTalk Services
- BizTalk Services and MyApp use WS-* security, coupled with the WCF binary message encoding.
- Other clients (Java, PHP, Ruby, whatever) can hit an HTTP endpoint hosted in the BizTalk Services "mesh". We will call this endpoint the HTTP Endpoint.
- Upon receipt of a message, the HTTP Endpoint tries to dispatch that message (or request) to MyApp.
If we use this set of steps with PictureServices, then you have a way to serve local pictures over the internet. If you just look at this task, there are lots of other ways to do this. I'm not suggesting that BizTalk Services is the next cool way to share photos. Instead, I think there are lots of cool apps that can take advantage of this kind of feature set.
Down to nuts and bolts - the service contract. PictureServices defines a service contract with operations for RSS, ATOM, and Simple list extensions. For the sake of time, I opted to have a single feature: get an RSS feed. Here's what the service contract looks like:
[ServiceContract]
interface IBTSPictureSyndication
{
[OperationContract(Action="GET", ReplyAction="GETRESPONSE")]
Message GetFeed();
}
The return type is System.ServiceModel.Channels.Message because the BizTalk Services SDK does not have full parity with the .NET Framework 3.5's capabilities. This will happen over time. To be honest, most of the head scratching I went through was due to the disparity between these two APIs.
Another interesting bit is the implementation of the GetFeed method. The syndication, the images, and all the thumbnail HTTP GETs (remember they are transformed) are going to flow through this one method. As a result, we have to test the requested address to determine which resource is being requested.
For that we turn to our new best friend: the UriTemplate. This is a new type introduced in .NET 3.5 - it makes URI parsing much easier (among other things).
There are 3 conditions I test for:
1) a request for the whole feed
2) a request for an image
3) a request for a thumbnail.
Here's the implementation:
[ServiceBehavior(AddressFilterMode=AddressFilterMode.Prefix)]
sealed class BTSPictureSyndication : IBTSPictureSyndication
{
String feedUri = "/Feed/";
String pictureUri = "/Feed/Picture/{pictureId}";
String thumbnailUri = "/Feed/Picture/t/{pictureId}";
PictureService service = new PictureService();
public Message GetFeed()
{
// get the To address and the base address
Uri to = OperationContext.Current.RequestContext.RequestMessage.Headers.To;
Uri baseAddress = new Uri(ConfigurationManager.AppSettings["baseAddress"]);
// check to see if it's a request for the main feed
UriTemplate feedTemplate = new UriTemplate(feedUri);
UriTemplateMatch feedMatch = feedTemplate.Match(baseAddress, to);
if (feedMatch != null)
{
return GetMainFeed();
}
// check to see if it's a request for a picture
UriTemplate pictureTemplate = new UriTemplate(pictureUri);
UriTemplateMatch pictureMatch = pictureTemplate.Match(baseAddress, to);
if (pictureMatch != null)
{
String pictureId = pictureMatch.BoundVariables["pictureId"];
return GetPicture(pictureId);
}
// check to see if it's a request for a thumbnail
UriTemplate thumbnailTemplate = new UriTemplate(thumbnailUri);
UriTemplateMatch thumbnailMatch = thumbnailTemplate.Match(baseAddress, to);
if (thumbnailMatch != null)
{
String pictureId = thumbnailMatch.BoundVariables["pictureId"];
return GetPictureThumbnail(pictureId);
}
// we don't know what it is, so throw
throw new InvalidOperationException(String.Format("the address {0} was not matched", to.ToString()));
}
// use the service object to get the picture
private Message GetPicture(String pictureId)
{
return StreamMessageHelper.CreateMessage(OperationContext.Current.IncomingMessageVersion, "GETRESPONSE", service.GetPicture(pictureId));
}
// use the service object to get a thumbnail
private Message GetPictureThumbnail(String pictureId)
{
return StreamMessageHelper.CreateMessage(OperationContext.Current.IncomingMessageVersion, "GETRESPONSE", service.GetPictureThumbnail(pictureId));
}
// get the main feed (RSS)
private Message GetMainFeed()
{
Rss20FeedFormatter formatter = service.GetPicturesAsRss();
MemoryStream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream);
formatter.WriteTo(writer);
writer.Close();
stream.Position = 0;
return StreamMessageHelper.CreateMessage(OperationContext.Current.IncomingMessageVersion, "GETRESPONSE", stream);
}
}
Another thing that's worth pointing out is the presence of the AddressFilterMode property on the ServiceBehavior attribute annotation. This setting tells the WCF dispatching infrastructure to allow prefix matches to filter through to the method. In practical terms, this means that a request to http://foo/bar/baz would get dispatched to the same method as http://foo/bar. That's how we are returning the full feed, the image, or a thumbnail.
Here's a zipped version of the project (note that you must also have PictureServices).
-
Following on the heels of Steve Maine's post about namespaces in Syndication objects (Feeds, items, etc.), I thought it wise to plug the new stuff in PictureServices.
At the moment, PictureServices implements SLE (Simple List Extensions), and does a pretty crude job of it at that. Time permitting, I will add more support for field and group customization. For now, it serves as an example more than a carrier grade implementation. In any event, I used extension methods in the following type definition to make it easy to insert the right namespace declarations in the feed:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Syndication;
using System.Xml;
namespace Microsoft.DPE.Samples.SyndicationExtensions
{
// adds custom namespaces to an item or a feed
public static class SyndicationNamespaceHelper
{
public static void DeclareNamespace(this SyndicationFeed feed,
String prefix,
String ns)
{
XmlQualifiedName key = new XmlQualifiedName(prefix, NamespaceUris.XMLNamespace);
feed.AttributeExtensions.Add(key, ns);
}
public static void DeclareNamespace(this SyndicationItem item,
String prefix,
String ns)
{
XmlQualifiedName key = new XmlQualifiedName(prefix, NamespaceUris.XMLNamespace);
item.AttributeExtensions.Add(key, ns);
}
}
}
The usage model is simple - just new up a feed or an item, then call DeclareNamespace. Piece of cake.
-
Today I updated PictureServices to work with the RTM release of Visual Studio 2008 and the .NET Framework 3.5 (what a mouthful). My testing rigor for this release was less than perfect. Please let me know if you find any bugs.
For what it's worth, the changes in the API made the simple list extensions implementation simpler. Honestly, I was skeptical at first, but it really is pretty straightforward.
Check out the new version here.
-
I've received several mails about PictureServices and RTM. As some of you know, the Syndication API changed before RTM. The were subtle, but they did have an impact on the Picture Services project. Specifically, the simple list extensions part of Picture Services isn't up to date with the RTM bits. I will update the bits this week and repost...