Wednesday, September 07, 2016

MSMQ, WCF and IIS: Getting them to play nice: The extras, Part II

Here's another catch I've found that causes issues when trying to set up a 3-party queueing system: You need to log on interactively as the user that's accessing the queues on each of the machines where it's accessing the queues! This is so that a certificate can get created for the user on those machines to be used with Active Directory authentication.

Tuesday, September 06, 2016

Solving "m_safeCertContext is an invalid handle."

I've recently been trying to get an application working in Azure App Service that acts as a client who calls out to another service via WCF with TransportWithMessageCredential mode for security and Certificate mode for authentication. I've been getting the following error:

m_safeCertContext is an invalid handle.

According to this blog post, this error gets thrown when the certificate isn't correctly imported or has incorrect trust (for any of many possible reasons). Some of those reasons can include incorrect passwords, but there are others as well, like what I was encountering: in Azure App Service, there's no local user signed on when your application is running. Because of that, you run afoul of a subtle issue with managing certificates: all of the constructors, by default, use the user certificate store to temporarily store the PrivateKey of any loaded X509Certificate2 objects. Therefore, on an Azure App Service application, unless you use the new X509Certificate2(certBytes, passwordString, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable) constructor with the MachineKeySet | Exportable flags, your certificate will not be correctly read and will SILENTLY FAIL!!

Friday, September 02, 2016

Solving 'The remote certificate is invalid according to the validation procedure' with WCF channels

This typically happens most often (when using certificates) when the certificate Common Name (CN) doesn't match the DNS host name of the server.

Solving "Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled"

I've been trying to set up remote reads from an MSMQ queue to a WCF service hosted on another machine. I seem to have all my application settings correct, but I'm being screwed over by machine-level configuration on the service machine: the service machine won't run in Active Directory mode, no matter what I do.

After searching for the problem, I found this page on John Breakwell's MSDN blog. It describes the problem: essentially there's a legacy msmq object left around when you install MSMQ Server and Active Directory Integration features together in the same transaction. Here's how you **actually** fix the problem:


  1. Uninstall all of the MSMQ features.
  2. Execute this PowerShell command (or one similar to it) to actually delete the Active Directory object described in the article (which doesn't go into nearly enough detail on this point):  get-adobject -filter “name -eq ‘msmq'” | Where { $_.DistinguishedName -eq ‘CN=msmq,CN=MyAffectedServerNameHere,OU=Web Servers,OU=Member Servers,DC=MyDomainNameHere,DC=Network,DC=ads’} | Remove-ADObject
  3. Reinstall **just** MSMQ server, then reboot your machine.
  4. Reinstall **just** MSMQ active directory integration, then reboot your machine.
You should now be good to go.

Solving "Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled"

I've been trying to set up remote reads from an MSMQ queue to a WCF service hosted on another machine. I seem to have all my application settings correct, but I'm being screwed over by machine-level configuration on the service machine: the service machine won't run in Active Directory mode, no matter what I do.

After searching for the problem, I found this page on John Breakwell's MSDN blog. It describes the problem: essentially there's a legacy msmq object left around when you install MSMQ Server and Active Directory Integration features together in the same transaction. Here's how you **actually** fix the problem:


  1. Uninstall all of the MSMQ features.
  2. Execute this PowerShell command (or one similar to it) to actually delete the Active Directory object described in the article (which doesn't go into nearly enough detail on this point):  get-adobject -filter “name -eq ‘msmq'” | Where { $_.DistinguishedName -eq ‘CN=msmq,CN=MyAffectedServerNameHere,OU=Web Servers,OU=Member Servers,DC=MyDomainNameHere,DC=Network,DC=ads’} | Remove-ADObject
  3. Reinstall **just** MSMQ server, then reboot your machine.
  4. Reinstall **just** MSMQ active directory integration, then reboot your machine.
You should now be good to go.

Thursday, September 01, 2016

Unblocking zip files, the permanent solution

My team recently migrated their code to Visual Studio Online (aka VSO aka VSTS), which means that any time we do our builds, we now have to download our build output through the browser as a zip file rather than copying from a file share as we formerly did when our code was built on-premise. As a consequence of this, we now stumble across a feature of Windows: automatic file blocking.

Any time we download a zip from the internet, any scripts extracted from it are automatically blocked by Windows using metadata attached to the file in the NTFS file system. This means we have to manually unblock our scripts every time we download a build and want to deploy it (But Alex, why aren't you deploying your systems automatically through a deployment manager ? Our company isn't there yet, but we're getting there). That said, there's a way to disable this feature, detailed here:

http://winaero.com/blog/disable-downloaded-files-from-being-blocked-in-windows-10/

The short of it is that there exists a group policy for disabling tracking of zone information for files downloaded from the Internet.

Start -> Run -> gpedit.msc -> Local Computer Policy -> User Configuration -> Administrative Templates -> Windows Components -> Attachment Manager -> "Do not preserve zone information in file attachments" : Enabled.

Done.

Wednesday, August 31, 2016

MSMQ, WCF and IIS: Getting them to play nice: The extras, Part I

I've recently been trying to set up queued publishing of data in my company within our internal applications so that we can publish that data out to other applications running in our hybrid cloud with Azure. To move the data around on-premise, I've been working off of the advice given to me by some very knowledgeable people in the IT space, and using architectural design patterns that have been proven to work (though not by me). To implement our new data-publishing architecture, I decided to leverage components I already had at my disposal and use WCF with MSMQ bindings to deal with unreliable connections from some of our remote sites. To help me get started, I began following the series of articles published here on MSDN by Tom Hollander. I was able to get past Part 1 of the tutorial without problem. I even needed the same architecture: a queued message client publishing to a service, via a queue hosted on a 3rd party system.

Part 2 however, securing the queue, proved to be a little bit harder, to the point where I needed to go to stackoverflow.com for help and posted this question. In the question, I kept running into an error when I tried to enable Transport security along with ActiveDirectory support. When I didn't enable ActiveDirectory support, I got a different error, with the code 0xC00E0030. Looking on the page for MSMQ queueing error codes on MSDN, I found that this error means that there was corrupted security data, somewhere. Here's what I had to do to resolve it:


  1. In the EndpointAddress for my WCF binding, I had to add an extra parameter to the constructor for the EndpointIdentity of my binding: New EndpointAddress(queueUri, EndpointIdentity.CreateDnsIdentity(queueUri.Host))
  2. I had to gain access to the server where I was hosting my MSMQ Server, and gain full access to the Server itself:  Computer Management -> Message Queueing -> Right-click -> Properties -> Security tab -> [my name] -> "Full Control"
  3. I had to re-register my own Internal Certificate for MSMQ on the server: [previous steps] -> User Certificate tab -> Internal Certificate section -> Renew....
After cleaning up the certificate and adding the endpoint, I was good to go, and I could now authenticate and send messages to the MSMQ server.

To be fair to Tom Hollander, he did say that there would be some extra specifics to getting Authentication working, and I guess these were mine. I have to send him a lot of thanks for going through what he did AND recording and publishing the steps. People like him make the world a better place.

Friday, August 26, 2016

Unable to add multiple listen rule keys or subscriptions to a Topic in an Azure Service Bus in an Azure Resource Group template

I recently ran across a problem wherein I was unable to add multiple Listen rules for my applications to my Topics in Azure Service Bus within an Azure Resource Group Template. I would run my template and it would fail to create the keys for the Topic or the Subscription for the topic of there was more than one of either of those for the Topic. It wouldn't even be consistent: it would switch back and forth between them between runs of the template. After a discussion with one of the Solution Architects at Microsoft, I found out there is, at the time of this writing, a bug in the Azure Resource Manager for Topics within Service Buses that prevents Topic access rules and subscriptions from being simultaneously created. As a work around, I was instructed to introduce an artificial dependency between each of the subscriptions to force the resource manager to create them serially rather than in parallel and this did the trick.

For example:

// TODO:

Tuesday, August 23, 2016

Getting verbose output from an Invoke-Command -ScriptBlock in PowerShell

It's often very useful to invoke commands on other machines, e.g. in deployment scripts. It can be even more useful to have logging of what actually gets executed on those other machines, e.g.

$myJob = Invoke-Command -AsJob -ScriptBlock {
    Param()

    Do-Thing -Verbose
}

However, in this instance, you wouldn't get the output of the Do-Thing command because it's writing to the Verbose stream of a script block being executed on a separate machine. Now, it's not that PowerShell can't collect the output of that Verbose stream for you, it can. You just need to instruct it how. The difference:

$myJob = Invoke-Command -AsJob -Verbose -ScriptBlock {
    [CmdletBinding()]
    Param()

    Do-Thing -Verbose
}

Now you'll be able to collect the Verbose output of your script block. The difference is that you need to pass the Verbose flag to the script block, and make it a cmdlet by adding the [CmdletBinding()] attribute to your block.