SoapUI screen font problem

On my virtual (VMWARE) windows development machines i sometimes experience a very annoying visual problem in SoapUI where text and menu-items disappear as i move the mouse around. As seen below the File and Tools menu options are gone.

2013-10-17 09_05_21-Win7x64-BTS2010 - VMware Workstation

After poking around in the SoapUI settings without luck i finally tried the Windows Visual Effects settings in Windows 7 and after disabling the “Smooth edges of screen fonts” everything works just fine again. 🙂

2013-10-17 09_13_32-Win7x64-BTS2010 - VMware Workstation

 

 

SoapUI 2-way SSL problem using PKCS12

If you like me spend a lot of time in the swiss-army-knife of webservice development called SoapUI when not in Visual Studio or PowerPoint, you could end up getting bitten by this problem.

 

Java based SoapUI has great built-in support for both consuming webservices and exposing mockservices using 2-way SSL aka. two-way or mutual SSL. It is a proven and interoperable way to exchange data in B2B and enterprise scenarios in a secure way. It means that during the TLS/SSL handshake the client proves its identity to the server using a PKI challenge the same way as the server does to the client in normal TLS/SSL. To allow this the client needs a client certificate with a corresponding private key.

 

Doing most of my work in .NET i tend not to use the JKS (Java Key Store) that much and to call a webservice requiring certificate authentication in SoapUI i just point to a PKCS12 file directly. The PKCS12 file (.P12 or .PFX) are easy to move to and from the windows certificate store and is one of the standard containers for certificates with private keys.

 

soapui

 

Normally this works perfect but if you are having trouble getting the SSL handshake to work one (of many) reason can be that the client certificate you are using has a trust chain including an intermediate CA which is getting more and more common.
The symptom is that SoapUI during the handshake simply wont participate in the client authentication thus leaving you with either a 403 or simmilar.

 

intermediateCA

 

In .NET this normally just works as you most likely have the complete chain of trusted certificate issuers in the Windows Certificate Store. But in SoapUI and other Java clients you can no longer rely just on the P12 file.

 

To solve this for SoapUI and other Java applications you need to create a JKS file containing the full certificate chain under the same alias.

 

1. Convert the PKCS12 to a JKS using Javas keytool.exe utility. You can find the utility in Javas JRE\BIN folder. If not elsewhere you have this together with the SoapUI installation.

 

jre\bin\keytool.exe -importkeystore -srckeystore MYCLIENTCERT.P12 -destkeystore MYCLIENTCERT.JKS -srcstoretype PKCS12 -deststoretype JKS -deststorepass password -srcstorepass password -destalias my-client-cert-alias -srcalias "my client cert"

 

2. Then you need all public certificates in the chain including both root and intermediate CA cert. Export them from windows certificate store in Base64 format (.CER)

 

3. Open all three files in a texteditor and chain them like this:
chain-certs
Save the file as my-complete-cert-chain.pem

 

4. Import the file to the JKS using
jre\bin\keytool.exe -import -keystore MYCLIENTCERT.JKS -alias my-client-cert-alias -file my-complete-cert-chain.pem

 

Now you got a JKS with your client certificate certificate chain that should work fine in SoapUI or in other Java-based webservice clients. 🙂

ASP.NET Web API support for ODATA $select

Since VS 2012.2 update ASP.NET Web API can take advantage of the ODATA Query parameters. Having the API consumer dictate part of the query can be powerful yet something that naturally needs some performance and security consideration before implementation.

Enabling the support is as simple as decorating the controller class or selected methods with the ActionFilterAttribute Queryable.

QueryableActionFilter

Now the API automatically supports things like $top, $orderby, $filter directly on the URL. 🙂

So a HTTP GET to http://server/service/api/wines?$top=2&filter=WineType eq ‘Red’ would get me this response

fiddler-without-select

You can control what queries to allow using properties on the ActionFilter Queryable.

One thing missing in the Web API ODATA implementation compared to the full-blown ODATA implementation in WCF Data Services is the $select keyword. The $select lets the API consumer pick what fields to return. With large objects this can save both bandwidth and serialization/deserialization performance.

The fact that ASP.NET Web API is open source in combination with the nightly-builds available on MyGet makes testing upcoming features super easy. Since a week or two back both $select and the $expand are available in the nightly-builds. (http://www.myget.org/gallery/aspnetwebstacknightly).

To install run this command:

install-package Microsoft.AspNet.WebApi.OData -pre -source http://www.myget.org/F/aspnetwebstacknightly

install-package-odata-nightly

After installation i can now make a HTTP GET like this
http://server/service/api/wines?&$top=2&$filter=WineType eq ‘Red’&$select=Id,Name and get only the ‘Id’ and ‘Name’ fields in the response.

with-select

 

The nightly-build i tried (5.0.0-beta1-130511) only had $select support when using JSON. With XML it causes a serialization exception. I guess supporting this with the DataContractSerializer would require alot more work compared to what they had to do with JSON.

Anyway – i think its a nice feature so thanks to the team working at getting this feature into the framework in a future release and the opportunity for me to beta-test it already today 🙂

Warmup of blog in new Azure home

I have now moved this blog to a new home in Windows Azure.

Pretty cool experience to see how seamless PHP/MYSQL based WordPress runs on Azure WebSites which is one of the PaaS features of Windows Azure.

One thing i have noticed working with Azure WebSites prior to this is the long initial load time after site has been idle for a while and the process is unloaded. This is easily solved by some keep-alive or warm-up task that periodically makes a HTTP GET to the site.

After reading a post by Sandrino Di Mattia i did this in Azure by using the Azure Mobile Services Job Scheduler which is currently in preview. This is probably not the intended usage of Mobile Services Job Scheduler but simple enough to be replaced with another solution if needed in the future.

The node.js script i use is shown here

Azure Mobile Services scheduled script
Azure Mobile Services scheduled script

The script is scheduled to run every 15 minutes which seems to do the trick both for ASP.NET and PHP based WebSites.

keep-alive-script-schedule

 

If the blog is not responsive – let me know 🙂

Connecting BizTalk with a mobile app using Azure Appfabric ServiceBus Queues, REST and WCF

The Azure Appfabric Service Bus 1.5 released in September had a feature I really have been looking forward to, durable queues and topics (pub/sub). A cloud based MSMQ ‘like’ queue can help both enterprise-enterprise scenarios as well as in connecting mobile applications with on-premise or cloud-hosted services in a reliable way.

Appfabric Service Bus queues and topics support three programming models:

 

  • .NET API
  • REST API
  • WCF Bindings

While the.NET API offers great control and simplicity, the REST API is supported on almost all platforms. Finally the WCF binding allows .NET programmers not having to learn yet another programming model.

In BizTalk the easiest way to utilize queues and topics are by the WCF binding NetMessagingBinding. Although we surely could use the REST API, just getting the security token out-of-band and keeping it updated, in the WCF-pipeline or elsewhere, would make it a bit cumbersome. NetMessagingBinding will automatically do the token acquisition before accessing the queue/topic.

If both sender and receiver use WCF things are pretty straight forward but if different programming models are used there are some things that need to be addressed.

Scenario

This scenario consists of an Android device which will use REST to send messages to a Service Bus queue then picked up by BizTalk using WCF.

I want the the client to be able to send any data (XML, text or binary) to the same Receive Location in BizTalk.

The Service Bus authorization is claims-based and the Azure Appfabric ACS (Access Control Service) is automatically configured when the Service Bus namespace is created. For simplicity I use ACS Service identities for both BizTalk and Android. In real world, the Android application would probably use something else such as an external IdP together with ACS. More on that in a later post!

Setup

Appfabric 1.5 SDK does not add entries to the machine.config as the previous versions did and we need those in BizTalk. I copy/pasted the necessary lines from http://msdn.microsoft.com/en-us/library/windowsazure/hh148155.aspx. Make sure to add them both to 32 & 64 bit machine.config!

Create a new one-way Receive Location hosted ‘in-process’ using the WCF-Custom adapter.

To be able to receive anything the client sends in the body of the HTTP POST we have to use CustomBinding instead of the pre-configured NetMessagingBinding. This allows us to replace the default TextMessageEncoding binding element with a WebMessageEncodingElement instead. Remember to move it above the NetMessagingTransport element after it is added.

WebMessageEncoding can output XML, JSON or binary data and it defaults to binary. It is possible to control this behavior using a custom WebContentTypeMapper but in this scenario it works fine with the default.

On the general tab enter the address of the already existing queue using the following format :  “sb://{servicebusnamespace}.servicebus.windows.net/{Queue}”.

Authentication and authorization

To receive messages from the queue the authorization will require a claim of type ‘net.windows.servicebus.action’ with value ‘Listen’.

The pre-configured ACS Service Identity ‘owner’ has this claim but it is considered more secure to create a separate identity with a shared symmetric key or an X509 certificate as identification. If you use something different than ‘owner’ do not forget to update the Rule Group to create the claim.

To specify how to authenticate against Service Bus add a TransportClient Endpoint Behavior and specify the identity and shared key to use.

Addressing

By default the NetMessageTransport assumes WCF and that WS-Addressing “To” is present in the message. So if you make a HTTP POST with a non-SOAP body to the queue the WCF trace will show that the adapter throws this exception:

The message with To ” cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver’s EndpointAddresses agree.

To fix this we need to insert the more forgiving Address Filter such as “System.ServiceModel.Dispatcher.MatchAllMessageFilter”. This must be done in a custom behavior extension.

namespace Kramerica.Extensions.WCF
{
    class MatchAllMessageFilterEndpointBehaviorExtensionElement : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get
            {
                return typeof(MatchAllMessageFilterEndpointBehavior);
            }
        }

        protected override object CreateBehavior()
        {
            return new MatchAllMessageFilterEndpointBehavior();
        }
    }

    class MatchAllMessageFilterEndpointBehavior : IEndpointBehavior
    {
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.AddressFilter = new System.ServiceModel.Dispatcher.MatchAllMessageFilter();
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }
    }
}

Add this BehaviorExtensionElement to machine.config (32 & 64-bit) in the behaviorExtensions section.

<add type="Kramerica.Extensions.WCF.MatchAllMessageFilterEndpointBehaviorExtensionElement, Kramerica.Extensions.WCF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1234567890123456"/>

Go to the Receive Location and add this in the EndpointBehaviors.

BizTalk message source

If you would make a REST HTTP POST to the queue now BizTalk would publish the message from WebMessageEncoding and it would look something like this:

<Binary>Qk3WAAAAAAAAADYAAAAoAAAA==</Binary>

This is Base64 encoded data and to fix that we just need to change what BizTalk publishes to the message box.

Go to the Messages tab and enter /*[local-name()=’Binary’] as the Body path expression and Base64 as Node encoding.

Now the WCF adapter will decode and publish everything inside <Binary> to the messagebox where a subscribing orchestration or send port can use the message.

Client

To test it I would use a REST capable test-client such Fiddler, SoapUI or the test client in WCF WEB API

Make a HTTP POST to “https://{servicebusnamespace}.servicebus.windows.net/{QueueName}/Messaging” with the token received from ACS in the authorization http header.

To test the mobile scenario i made a heavily simplified Android application that can send an image from the phones image gallery to the Azure Appfabric Service Bus Queue.

    public void button_SendImage_OnClick(View view) {
    	if (selectedImage!=null)
    	{
    		try {
    			getTokenFromACS();
    			sendImageToHQ();
    		} catch (Exception e) {
    			Toast.makeText(getApplicationContext(), e.getMessage(),1).show();
    		}
    	}
    }

	private void getTokenFromACS() throws ClientProtocolException, IOException {

		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(ACSBASEADDRESS);

		List<NameValuePair> parameters = new ArrayList<NameValuePair>(3);
		parameters.add(new BasicNameValuePair("wrap_scope", RELYINGPARTYADDRESS));
		parameters.add(new BasicNameValuePair("wrap_name", ISSUER));
		parameters.add(new BasicNameValuePair("wrap_password", ISSUERSECRET));

		httppost.setEntity(new UrlEncodedFormEntity(parameters, HTTP.UTF_8));

		BasicHttpResponse httpResponse = null;
	    httpResponse = (BasicHttpResponse) httpclient.execute(httppost);

		String response = null;
		response = EntityUtils.toString(httpResponse.getEntity());

		String[] tokenVariables = response.split("&");
		String[] tokenVariable = tokenVariables[0].split("=");
		authorizationToken = java.net.URLDecoder.decode(tokenVariable[1]);
	}

	private void sendImageToHQ() throws ClientProtocolException, IOException {
		String queueAddress = SERVICEADDRESS + QUEUENAME + "/messages?timeout=60";

		HttpClient httpclient = getSSLReadyHttpClient();
		HttpPost httppost = new HttpPost(queueAddress);

		httppost.setHeader("Content-Type", "image/jpg");
		httppost.setHeader("Authorization", "WRAP access_token="" + authorizationToken + """);

		ByteArrayOutputStream out = new ByteArrayOutputStream(100240);
		selectedImage.compress(CompressFormat.JPEG, 100, out);

		httppost.setEntity(new ByteArrayEntity(out.toByteArray()));
		HttpResponse response = httpclient.execute(httppost);

		if (response.getStatusLine().getStatusCode() == 201)
			Toast.makeText(getApplicationContext(), "Image sent to queue!", 1).show();
		else
			Toast.makeText(getApplicationContext(), "Image NOT sent to queue! Reponse was : " + response.getStatusLine(), 1).show();
}

Code handling image-resize and some basic Android stuff are not shown above.

In BizTalk we now get the binary representation of the image published to the messagebox and a simple FILE Sendport makes the image viewable. In a real world scenario, metadata about the image could go as custom http headers or similar.

The takeaway here is that we can use the same queue and BizTalk Receive Location no matter what client or Service Bus API (WCF, REST or .NET) is used on the other side!

BizTalk, Claims and Windows Identity Foundation

Being a fan of Microsoft’s Windows Identity Foundation and its claims and federation based approach to identity i have been interested in how well it fits into BizTalk. Even though BizTalk does not provide any built-in support for the Windows Identity Foundation classes its support for WCF-bindings such as WS2007FederationHttpBinding gives support for WS-Trust and SAML tokens issued by external Security Token Services (STS).

I this scenario a Security Token Service (STS) are used to issue tokens to clients who are using the WS-Trust protocol and the WS2007FederationHttpBinding. The token is passed on to the service hosted in BizTalk. I use an test-STS based on Windows Identity Foundation but any STS supporting the WS-Trust protocol will do.

Claims-based authorization

With BizTalk hosting the service, as in any WCF service hosting scenario, authentication and authorization of the caller are best made in the WCF-channel. As the WIF-based extension ClaimsAuthorizationManager is not an option, i can use the standard WCF ServiceAuthorizationManager to determine access as i do in the simplified example below. In this scenario only persons of 18 years or older, based on a date-of-birth claim inside the received token, will be allowed access.

    public class GottorpServiceAuthorizationManager : ServiceAuthorizationManager
    {
        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            foreach (ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
            {
                foreach (System.IdentityModel.Claims.Claim c in cs.FindClaims("http://soapfault.com/claims/dateofbirth", Rights.PossessProperty))
                {
                    int age = new DateTime(DateTime.Now.Subtract(DateTime.Parse(c.Resource.ToString())).Ticks).Year-1;

                    if (age >= 18)
                        return true;
                }
            }
            return false;
        }
    }

 

You specify the ServiceAuthorizationManager by adding a ServiceAuthorization behavior and specify the class in the serviceAuthorizationManagerType property as seen below.

Claims inside BizTalk

One obvious thing missing with BizTalk is that the WCF-adapters does not flow the claims received into the BizTalk message-context where it could be used for routing, business-logic or similar. As a comparison, in ASP.NET or WCF an IClaimsPrincipal provided by WIF will contain the claims but in BizTalk they are lost when the message hits the BizTalk messagebox.

In scenarios where access to the claims inside BizTalk are needed one solution is to copy them to the message-context with the help of a custom WCF MessageInspector. This will place the claims into the message header that later, by the use of a brilliant built-in WCF-adapter feature, will automatically get transferred to the message-context. The code below is a simplified example on how this can be done with token claims.

    public partial class BizTalkContextClaimsMessageInspector : IDispatchMessageInspector
    {
        const string WRITE_PROPERTIES_NAMESPACE =   "http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties/WriteToContext";
        const string PROMOTE_PROPERTIES_NAMESPACE = "http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties/Promote";
        const string CLAIMTYPE_TO_COPY = "http://soapfault.com/claims";

        public object AfterReceiveRequest(
            ref System.ServiceModel.Channels.Message request,
            System.ServiceModel.IClientChannel channel,
            System.ServiceModel.InstanceContext instanceContext)
        {

            var context = OperationContext.Current;
            var properties = new List<KeyValuePair<XmlQualifiedName, object>>();

            foreach (ClaimSet cs in context.ServiceSecurityContext.AuthorizationContext.ClaimSets)
            {
                foreach (Claim c in cs.Where(q => q.ClaimType == CLAIMTYPE_TO_COPY))
                {
                    var prop = new XmlQualifiedName(
                        c.ClaimType.Substring(c.ClaimType.LastIndexOf("/") + 1),
                        c.ClaimType.Substring(0, c.ClaimType.LastIndexOf("/")));
                    properties.Add(new KeyValuePair<XmlQualifiedName, object>(prop, c.Resource));
                }
            }

            //use WRITE_PROPERTIES_NAMESPACE or PROMOTE_PROPERTIES_NAMESPACE
            request.Properties[PROMOTE_PROPERTIES_NAMESPACE] = properties;

            return null;
       }

 

I can choose if the values simply should be written to the message context or if they also should be promoted by selecting one of two namespaces when writing the request (see code sample above). Note that if they are to be promoted, which is necessary to do routing, a property-schema must be deployed and the value must not exceed 256 characters.

As with any WCF MessageInspector i also need an EndpointBehavior and BehaviorExtensionElement to place it into the WCF-channel.

    public class BizTalkContextClaimsEndpointBehavior : IEndpointBehavior
    {

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            return;
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            return;
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            var messageInspector = new BizTalkContextClaimsMessageInspector();
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(messageInspector);
        }

        public void Validate(ServiceEndpoint endpoint)
        {
            return;
        }
    }

    class BizTalkContextClaimsBehaviorExtensionElement : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get
            {
                return typeof(BizTalkContextClaimsEndpointBehavior);
            }
        }

        protected override object CreateBehavior()
        {
            return new BizTalkContextClaimsEndpointBehavior();
        }
    }

To activate it should be registed in the <behaviorExtensions> section in machine.config. Note that if you are running on 64-bit host do this in both 32 & 64 -bit machine.config as the MMC-based BizTalk Server Administration Console always runs in 32-bit. After registration and restarting Administration Console i can add the EndpointBehavior on my ReceiveLocation.

 

Now when a request is received and the message is published in BizTalk messagebox the claims are available in the message context.

They can now be used in orchestrations, pipeline components or for routing purposes.

PivotViewer to present data in a cool way

I have tried the Silverlight control PivotViewer that can be used to present large amounts of data in a fun and intuitive way. Inspired by things like the Netflix Pivotviewer demo i have been wanting to do something with it. Gary Flake made a fantastic presentation on what can be done with this technology at TED 2010.

This is how the result looks!

Being completely useless in GUI design i liked the PivotViewer approach of having most of the look and feel in the control itself and all i had to do was to create a valid collection.

After finding a really good xml feed of items in the booli.se api, which presents Swedish real estate ads, i made a simple app converting that into Pivot Collection and the DeepZoom structure needed. Real estate ads and this control is a perfect match if you ask me. A big thanks to booli.se for providing this api.

To create the collection and help with DeepZoom i used the pAuthor C# library available on codeplex. When the collection and deepzoom stuff is ready to go it is just a matter of adding the control to a simple silverlight app and load the collection.

As an alternative to my approach of creating the collection using code you could generate it using XSLT or even by an Excel 2010 plugin.

Follow the link and you can see how it looks when finished. Try out the filtering on the left!

Click here to open the POC in a separate window!