De Microsoft .Net Service Bus en de Microsoft Access Control Service gecombineerd
Afgelopen jaar kondigde Ray Ozzie op de Professional Developer Conference het Windows Azure Services Platform aan. Het Azure Services Platform is een omgeving voor het draaien van applicaties en het opslaan van gegevens in Microsoft data centra, die zich overal ter wereld bevinden. Bedrijven kunnen ervoor kiezen om daar nieuwe applicaties te hosten, maar je kan er ook voor kiezen bestaande applicaties te verrijken met individuele services die in de “Cloud” draaien.
Microsoft .Net services bestaan uit een set services voor developers en een SDK om .NET applicaties in de “Cloud” te kunnen draaien. Je kunt aan .Net services denken als een nieuw .Net framework maar dan specifiek voor dit type applicaties. Dit framework bestaat uit services, die gebaseerd zijn op standaard protocollen, zodat elk service platform erop kan aanhaken. Denk daarbij aan SOAP, REST en WS* technieken. Wanneer je als developer gewend bent om te werken met Windows Workflow Foundation en Windows Communication Foundation, dan zul je het niet moeilijk vinden om met de .Net services SDK te werken. Wil je er direct mee aan de slag? Je kunt dan de SDK downloaden van http://www.microsoft.com/azure en een code aanvragen om je eigen solution aan te kunnen maken.
Op dit moment bestaan de .Net services uit een drietal services voor het regelen van connectiviteit, toegang en workflow, te weten:
- Microsoft .Net Service Bus: een netwerk infrastructuur voor het verbinden van applicaties over het Internet;
- Microsoft .Net Access Control Service: op claims gebaseerde toegang waarbij het kan werken met identity providers als Active Directory en Windows Live ID;
- Microsoft .Net Workflow Service: een infrastructuur voor het managen en hosten van workflows.
Dit artikel beschrijft de Microsoft .Net Service Bus in combinatie met de Microsoft .Net Access Control Service.
Microsoft .Net Service Bus
In de praktijk zien we dat het nog steeds een uitdaging is om applicaties met elkaar te verbinden. Om dit mogelijk te maken gebruiken organisaties een Enterprise Service Bus (ESB). De Microsoft .Net Service Bus heeft een gelijkwaardige architectuur. Het verschil zit hem in het blikveld en de probleemstelling. Immers de .Net Service Bus moet op een globaal internet niveau kunnen draaien en dat ook nog eens met hoge inzet. Met de Microsoft .Net Service Bus kun je je huidige ESB verbinden met services die in de “Cloud” draaien, maar je kunt de .Net Service Bus ook inzetten om applicaties met elkaar te verbinden die zich op verschillende fysieke locaties achter een firewall bevinden.
Architectuur
Om beter te kunnen begrijpen hoe de Microsoft .Net Service Bus werkt, is de architectuur ervan te zien in figuur 1. Hieronder worden verschillende onderdelen van de architectuur besproken aan de hand van een listing.

Figuur 1
Om een applicatie in de “Cloud” te laten draaien moet je een nieuwe Azure solution aanmaken op http://www.microsoft.com/Azure. Voor dit artikel heb ik de solution AzureExample aangemaakt (zie figuur 2).

Figuur 2
In het voorbeeld gebruiken we een client project en een service project. Listing 1 toont het service contract en een operatie die twee integers verwacht. Listing 2 definieert de service die twee getallen met elkaar vermenigvuldigt. Hieronder wordt besproken hoe we deze service via de servicebus beschikbaar gaan maken en hoe we hem kunnen gaan gebruiken.
namespace Services
{
[ServiceContract (Name="SampleContract", Namespace=
"http://azureexample.microsoft.com/ServiceModel/Relay")
]
interface ISampleContract
{
[OperationContract]
int Sample(int getal, int multiplier);
}
}
Listing1
namespace Services
{
[ServiceBehavior(Name="SampleService", Namespace=
"http://azureexample.microsoft.com/ServiceModel/Relay/")
]
public class SampleService: ISampleContract
{
public int Sample(int getal, int multiplier)
{
return getal * multiplier;
}
}
}
Listing2
Naamgeving
Laten we allereerst eens naar de naamgevingstrategie kijken. De basis van het naamgevingsysteem is oplosbaar door traditionele DNS technieken. Het is aan de eigenaar van de solution om de hiërarchische namespace te controleren. De manier waarop je het moet indelen is als volgt:
[scheme]://[solution-naming-scope]/[name]/[name]
De naamgeving van de URI is onder te verdelen in een drietal onderdelen. De CTP release van november ondersteunt de schemes SB en HTTP, waarbij je HTTP gebruikt voor de op HTTP gebaseerde endpoints en SB voor alles wat anders is (bijvoorbeeld TCP). De solution-naming-scope beschrijft de solution binnen het Azure platform en bestaat uit
servicebus.windows.net/services/[solution]
Als laatste definieer je de endpoint namen. Alles wat na [solution] komt in het pad is onderdeel van de door de gebruiker gedefinieerde namespace. Je kunt een onbeperkte hoeveelheid endpoint namen opgeven door een hiërarchie van namen achter [solution] te plakken in het pad. Voor het listing in dit artikel ziet de uri er als volgt uit:
sb://servicebus.windows.net/services/AzureExample/
SampleService
Twee verschillende services binnen de solution hoeven niet op dezelfde machine of in hetzelfde netwerk te worden gehost. Het is de taak van de Service Bus om te bepalen waar de endpoints zich bevinden.
Service Registry
Naast de naming convention biedt de Service Bus een Service Registry voor het publiceren en ontdekken van service endpoints binnen een solution. Dit kan zowel automatisch als handmatig. Het handigst is om dit automatisch door de Service Bus te laten regelen.
//Definieer credentials. Username en
//password van de solution.
TransportClientEndpointBehavior
userNamePasswordServiceBusCredential =
new TransportClientEndpointBehavior();
userNamePasswordServiceBusCredential.CredentialType =
TransportClientCredentialType.UserNamePassword;
userNamePasswordServiceBusCredential.Credentials.
UserName.UserName = solutionName;
userNamePasswordServiceBusCredential.Credentials.
UserName.Password = solutionPassword;
//Endpoint adres
Uri address =
new Uri(
String.Format("sb://{0}/services/{1}/SampleService/",
ServiceBusEnvironment.DefaultRelayHostName,
"AzureExample"));
ServiceHost host =
new ServiceHost(typeof(SampleService), address);
// Voeg de credentials aan alle endpoints toe
foreach (ServiceEndpoint endpoint
in host.Description.Endpoints)
{
endpoint.Behaviors.Add
(userNamePasswordServiceBusCredential);
}
// Open de host
host.Open();
Console.WriteLine("Service address: " + address);
Console.WriteLine("Press [Enter] to exit");
Console.ReadLine();
host.Close();
Listing 3
In listing 3 is te zien hoe we een endpoint adres aanmaken voor onze SampleService. Voor authenticatie met de Service Bus wordt de username en password gebruikt die je hebt opgegeven bij het aanmaken van de solution in Azure. Op basis van de configuratie (listing 4) maken we een host aan. De credentials worden aan elk endpoint toegevoegd. In dit geval is dat er maar een, namelijk SampleService. Vervolgens wordt de host geopend (figuur 3).

Figuur 3
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpRelayBinding>
<binding name="default" />
</netTcpRelayBinding>
</bindings>
<services>
<service name="Services.SampleService">
<endpoint name="RelayEndpoint"
contract="Services.ISampleContract"
binding="netTcpRelayBinding"
bindingConfiguration="default"
address="" />
</service>
</services>
</system.serviceModel>
</configuration>
Listing 4
De client applicatie is op een zelfde wijze geconfigureerd (listing 5) als de service applicatie.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpRelayBinding>
<binding name="default" />
</netTcpRelayBinding>
</bindings>
<client>
<endpoint name="RelayEndpoint"
contract="AzureSample.ISampleContract"
binding="netTcpRelayBinding"
bindingConfiguration="default"
address="" />
</client>
</system.serviceModel>
</configuration>
Listing 5
Relay
In het hart van de Service Bus bevindt zich de Relay Service (figuur 4) om door firewalls en NAT heen te kunnen communiceren. De relay maakt het mogelijk voor een zender om met een ontvanger te communiceren door middel van een adres. In het code voorbeeld is dat
[sb://servicebus.microsoft.net/services/AzureExample/
SampleService]

Figuur 4
De ontvanger is door middel van een naar buiten openstaande poort verbonden met de Relay Service en specificeert het adres waarnaar hij wil luisteren. De zender kan dan een bericht verzenden door hetzelfde adres te specificeren. Vervolgens kan de Relay Service het bericht doorgeven aan de ontvanger die op hetzelfde adres zit. De ontvanger hoeft geen inbound poorten open te hebben staan.
De Relay Service ondersteunt de volgende messaging patronen:
- One-way
- Request/response
- Peer-to-peer
- Publish/subscribe scenarios
- Connection-oriented bi-directional socket communication
Wanneer je gebruik maakt van de Relay Service leg je de luisterverantwoordelijkheid bij de Relay Service. Om gebruik te kunnen maken van de Relay Service leg je een connectie tussen je lokale service en de Relay Service. Binnen .Net doe je dit door het WCF programmeermodel en -bindings die in de SDK zitten te gebruiken. Deze bindings worden dan omgezet naar nieuwe transport bindings om WCF listeners te maken die met de Relay Service integreren. Voor de Relay Service is het nodig dat een aantal outbound poorten open staan, te weten 808 (TCP connecties), 828 (TCP/SSL connecties) en poorten 818 en 819 voor geavanceerde TCP connecties. Wanneer je binnen een omgeving werkt die alle outbound connecties blokkeert, behalve diegene die gebruikt worden door HTTP/HTTPS, dan kun je een speciale HTTP gebaseerde verbindingsoptie gebruiken.
De listing gebruikt de binding NetTCPRelayBinding aangezien Microsoft deze binding als default aanraadt. Hij is zeer efficiënt en maakt een publiekelijk te bereiken endpoint aan in de Relay Service. Client applicaties moeten geconfigureerd worden met dezelfde binding. Deze binding ondersteunt drie soorten verbindingen:
- Relay: alle communicatie gaat via de relay service;
- Hybride: de initiële communicatie gaat via de relay service waarna zender en ontvanger een directie communicatie met elkaar hebben. Deze communicatie wordt wel gecoördineerd door de relay service;
- Direct: zonder relay service. In de CTP werkt dit nog hetzelfde als de hybride connectie.
Naast de binding getoond in bovenstaand voorbeeld, zijn er nog de volgende mogelijkheden:
| Standaard WCF Binding |
Vergelijkbare Relay Binding |
| BasicHttpBinding |
BasicHttpRelayBinding |
| WebHttpBinding |
WebHttpRelayBinding |
| WSHttpBinding |
WSHttpRelayBinding |
| WS2007HttpBinding |
WS2007HttpRelayBinding |
| WSHttpContextBinding |
WSHttpRelayContextBinding |
| WS2007HttpFederationBinding |
WS2007HttpRelayFederationBinding |
| NetTcpBinding |
NetTcpRelayBinding |
| NetTcpContextBinding |
NetTcpRelayContextBinding |
| N/A |
NetOnewayRelayBinding |
| N/A |
NetEventRelayBinding |
Tabel 1: Relay bindings
De relay bindings werken ongeveer identiek aan de WCF bindings. Het is een uitdaging om te weten welke binding je exact nodig hebt. De NetTcpRelayBinding wordt als default aangeraden, maar je zou je kunnen voorstellen dat deze wellicht niet zou volstaan omdat outbound TCP poorten nodig zijn voor de luisteraar. Je zou dan bijvoorbeeld de NetOnewayRelayBinding kunnen gebruiken. Deze is wat aggressiever en maakt gebruik van HTTP poorten 80/443 die meestal open staan.
Een Relay Service werkt als een omgeving die compleet los staat van de lokale omgeving, wat het mogelijk maakt om ongewild verkeer tegen te houden voordat het bij je service-omgeving uitkomt. Het verbergt ook alle informatie over de netwerklocatie.
Het idee van een Relay Service is niet nieuw. Ook Groove gebruikt een Relay Service voor het uitwisselen van documenten.
Authenticatie en autorisatie
De Microsoft .Net Service Bus vraagt van elke ontvanger om geauthenticeerd en geautoriseerd te zijn voor een specifieke URI, voordat het een listener maakt voor die ontvanger. Dit geldt ook voor clients die willen dat de Service Bus berichten voor hen relayt, al kun je dat voor de client wel uitzetten wanneer je je endpoints configureert. Authenticatie kun je laten regelen door de Access Control Service. Vervolgens is het dan aan de Access Control Service om de claims aan de .Net Service Bus te produceren voor autorisatie. Het verschil tussen authenticatie en autorisatie zit hem in wie je bent en wat je mag doen. De Service Bus is zo ontworpen dat het de Access Control Service vertrouwt. De Service Bus zoekt naar claims in de “security tokens” die meegegeven worden door zenders en ontvangers. Er zijn maar twee claims waarnaar gezocht wordt, namelijk #send en #listen. Wanneer die gevonden zijn en er is niet gerommeld met het security-token dan wordt toegang gegeven.
Wanneer een zender of ontvanger met solution credentials of met een security-token op de proppen komt dan maakt de .Net Access Control Service een rules gedreven beslissing of een autorisatie-token wordt afgegeven aan in dit geval de Microsoft .Net Service bus. De Access Control Service signt en encrypt het security-token zodat de claims alleen gelezen kunnen worden door de .Net Service Bus. Alleen de Service Bus kan de informatie decrypten en lezen. Wanneer het bericht richting de ontvanger gaat wordt het autorisatie-token verwijderd. Dit heeft de ontvanger immers niet nodig.
De listing maakt gebruik van een managed card van de Security Token Service, welke bekend staat als Microsoft Identity Lab (https://ipsts.federatedidentity.net/MgmtConsole/Default.aspx), waar een account is aangemaakt. Daarnaast moeten we voor de Access Control Service nog wat aanpassingen maken aan de solution in Azure (http://portal.ex.azure.microsoft.com/default.aspx). Allereerst moeten we de scope toevoegen aan de solution, waarbij je kiest voor de Service Bus. Vervolgens klik je op identity issuer en voeg je https://ipsts.federatedidentity.net toe. Binnen het lab is een account aangemaakt onder de groep Domain Users. Daarom wordt ook een claim type toegevoegd met de naam Group en de waarde Domain Users. Wanneer je dan naar Rules gaat dan zie je dat er al een Send en Listen rule is aangemaakt. Daar maak je nog een extra rule aan om aan te geven dat de receiver tot de groep Domain Users moet behoren. De servicebus authentiseert in listing 6 de client door Windows Cardspace informatie te geven. Hier kun je aangeven, dat je verwacht dat het token een claimtype group heeft. Vervolgens wordt een channel geopend en kan de service geconsumeerd worden. Tijdens het draaien van de code wordt om je credentials gevraagd (figuur 5).

Figuur 5
string serviceUserName = Console.ReadLine();
//Adres
Uri serviceUri =
new Uri(
String.Format("sb://{0}/services/{1}/SampleService/",
ServiceBusEnvironment.DefaultRelayHostName,
serviceUserName));
//Federatie via cardspace
TransportClientEndpointBehavior behavior =
new TransportClientEndpointBehavior();
behavior.CredentialType =
TransportClientCredentialType.FederationViaCardSpace;
behavior.Credentials.FederationViaCardSpace.
ClaimTypeRequirements.Add(new ClaimTypeRequirement
("http://ipsts.federatedidentity.net/group"));
EndpointAddress address =
new EndpointAddress(serviceUri);
//Channel
ChannelFactory<ISampleChannel> channelFactory =
new ChannelFactory<ISampleChannel>("RelayEndpoint",
new EndpointAddress(serviceUri));
channelFactory.Endpoint.Behaviors.Add(behavior);
ISampleChannel channel = channelFactory.CreateChannel();
channel.Open();
Listing 6
Conclusie
De .Net Service Bus is een veilige, op standaarden gebaseerde manier van het verbinden van applicaties over het internet. .Net Developers kunnen hun voordeel doen met de Service Bus door simpelweg te kiezen uit een geheel nieuwe set WCF-bindings. De rest van de WCF-code blijft eigenlijk hetzelfde.
Op security vlak verbergt de Service Bus alle informatie over de netwerklocatie en biedt het een omgeving die compleet los staat van de lokale omgeving. Op deze manier kunnen kwaadwillenden door de Service Bus worden gestopt voordat het te laat is.
Door de Microsoft .Net Service Bus en de Microsoft Access Control Service te combineren is het mogelijk om op een makkelijke en veilige manier applicaties met elkaar te verbinden. Zelfs door firewalls heen.
Links
Je kunt alles vinden over dit onderwerp op http://www.microsoft.com/azure. Bekijk tevens alle presentaties over Azure op http://www.microsoft.com/pdc.