Friday, May 18, 2012

Installing MonoDevelop 3 on Ubuntu Oneiric and Mint 12

I really like being able to develop in .NET on linux, and I think that the mono team has come a long way in its efforts to make mono-based applications production-viable.  Sadly, I'm guessing that the majority of mono developers use mac, opensuse, or windows because those are the only platforms that dependably have pre-built binaries and installers.  Since I use Mint (a variant of Ubuntu), I'd really like a simple method for installing a current version of MonoDevelop.

Recently, I needed to install Mint on my new laptop and so I payed close attention to how I installed MonoDevelop and turned it into a script -- which you can now use!  I've tested it on a fresh Mint 12, but it should also work on Ubuntu Oneiric.

The script:

  1. Installs the git client and the dependencies necessary to build MonoDevelop from source.
  2. Downloads the source code for MonoDevelop from github.
  3. Configures the build script to install the stable profile into /usr/local (/usr/local/monodevelop-3.0.1/ will be the full path).  However, you can change the defaults by editing the variables at the top of the script.  
  4. Builds and installs MonoDevelop
  5. Creates a script in $INSTALL_PREFIX/bin that simply calls the real monodevelop script.  This is because you can't just create a symbolic link.  This step has a bad smell to it - if you know a better way to do what I'm trying to do, please leave a comment.
  6. Adds two environment variables into your ~/.bashrc file
You should also know that it has a dependency on gnome-sharp2, so I don't know what to do if you're not using something based on gnome.  If you want to save some hard drive space after the install, you can delete the MonoDevelop source code directory that gets downloaded.

You can download it here: https://raw.github.com/jar349/tools/master/install-monodevelop.sh.

Don't forget to run it with sudo!


Thursday, April 12, 2012

Installing CouchDB 1.2 on CentOS 6

CouchDB has a really great idea behind it.  Whether or not CouchDB delivers on it, I've been wanting to discover for a while.  Only way to do that is kick the tires, so I started the process of figuring out how to install it.

First disappointment is discovering a general lack of documentation.  But my first appreciation is how simple it is once you figure out what needs to be done.

CouchDB runs on erlang, so you need to install erlang from the EPEL repository.  In order to use that repository on CentOS 6, run the following command:
sudo rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
Now you can install erlang:
sudo yum install erlang
That will bring with it a number of dependencies, such as wxWidgets.  With erlang now available, it's time to download the CouchDB source code from here. As of this writing, the latest release is 1.2.0, although 1.3 is in alpha in master.  I'm electing to use the stable release.

Now that you have the source, unpack, configure, build, and install it.
tar zxvf apache-couchdb-1.2.0.tar.gz
./configure --with-erlang=/usr/lib64/erlang/usr/include
make
sudo make install
If you want to be able to reach the database from other computers on the network, you'll want to edit the configuration file:
sudo emacs /usr/local/etc/couchdb/local.ini
Under the [httpd] section, uncomment the bind_address setting and change the value to 0.0.0.0 if you want couchdb to listen on all available interfaces.

Also, since you've installed from source instead of from a package, let's configure CouchDB to run as a daemon that starts up when we boot.
sudo ln -s /usr/local/etc/rc.d/couchdb /etc/init.d/couchdb
sudo chkconfig --add couchdb
sudo chkconfig --level 345 couchdb on
Finally, let's create a couchdb service account that will run CouchDB, and then fix some file permissions to give the service account access to what it needs at runtime.
sudo adduser -r --home /usr/local/var/lib/couchdb -M --shell /bin/bash --comment "CouchDB Administrator" couchdb
sudo chown -R couchdb: /usr/local/var/lib/couchdb /usr/local/var/log/couchdb /usr/local/var/run/couchdb /usr/local/etc/couchdb
That's it!  You've installed CouchDB on CentOS 6!  Start the database with:
sudo service couchdb start
 You should now be able to get the welcome result by browsing to http://localhost:5984/ (unless, of course, you just installed it on a remote machine).

Time to Relax!


Tuesday, January 10, 2012

Invalid provider type specified when accessing X509Certificate2.PrivateKey

Today, I was attempting to digitally sign a byte array with my private key so that I could produce an event on the event bus and a consumer could ensure that the message came from me and was not modified while in transit.

public byte[] SignData(byte[] data)
{
  X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
  certStore.Open(OpenFlags.ReadOnly);

  // the DN I get is CN=name,CN=Users,DC=example,DC=com
  // but the DN on the cert has spaces after each comma
  string spacedDN = UserPrincipal.Current.DistinguishedName.Replace(",", ", ");

  X509Certificate2 cert = certStore.Certificates
    .Find(
      X509FindType.FindBySubjectDistinguishedName,
      spacedDN,
      true)
    .OfType<X509Certificate2>()
    .FirstOrDefault();

  if (null == cert) { // handle no cert }

  RSACryptoServiceProvider rsaProvider = cert.PrivateKey as RSACryptoServiceProvider;
  return rsaProvider.SignData(data, new SHA1CryptoServiceProvider());
}

When I run this as myself, I get the following exception:  
System.Security.Cryptography.CryptographicException: Invalid provider type specified.
... the stack trace boils down to ...
System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
This wasn't a terribly enlightening exception message, so I asked google and found this link and this link.  It turns out that by using the newest Certificate Templates (version 3), I am using Microsoft's new Key Storage Provider (KSP), and not the Cryptographic Storage Provider (CSP) that we normally expect.  Windows Server 2008-based certificate templates use the KSP as part of what M$ calls Cryptography Next Generation (CNG).  While .NET 4 does provide managed implementations of the CNG stuff, they are not FIPS-compliant, which is a deal-breaker for me.

So what is a FIPS-constrained boy to do?  Well, I had to delete my auto-enrollment templates that were Windows Server 2008-based and replace them with Windows Server 2003-based templates.  When you duplicate a template using the Certificate Templates MMC snap-in, it will ask you to choose between 2008-based and 2003-based.  Select 2003-based and then revoke any certs you may have issued based on the 2008-based templates.  Let auto-enrollment take its course and then you'll find that you no longer get the invalid provider exception when you access your private key.

Tuesday, December 27, 2011

Establishing a SSL connection to RabbitMQ using the .NET client

First, I'm making the assumption that you've read, re-read, and followed the SSL tutorial on rabbitmq's website.  If you haven't done everything that it's instructed you to do (including adding your certificates to the Windows Certificate Store using certmgr), none of this code is going to work for you.  If you have, this code should "Just Work™".

Here's the complete code file that works for me.  You will (obviously) need to change the names of the servers, and the thumbprint of your certificate.

Note that this code only uses your client and server's certificates to establish a secure connection.  You are still logging in as guest.  I will show you how to use your client certificate to authenticate yourself below.
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;

using RabbitMQ.Client;
using RabbitMQ.Util;


namespace RabbitSslTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Start();

            Console.WriteLine();
            Console.WriteLine("Press <ENTER> to exit.");
            Console.ReadLine();
        }


        public void Start()
        {
            try
            {
                // we use the rabbit connection factory, just like normal
                ConnectionFactory cf = new ConnectionFactory();

                // set the hostname and the port
                cf.HostName = "rabbitmq-server";
                cf.Port = AmqpTcpEndpoint.DefaultAmqpSslPort;

                // I've imported my certificate into my certificate store
                // (the Personal/Certificates folder in the certmgr mmc snap-in)
                // Let's open that store right now.
                X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                store.Open(OpenFlags.ReadOnly);

                // and find my certificate by its thumbprint.
                X509Certificate cert = store.Certificates
                    .Find(
                        X509FindType.FindByThumbprint,
                        "6d 36 c0 f9 c2 f8 72 05 d1 01 6c 54 e1 91 bb 2d 66 7b ac 94",
                        true
                    )
                    .OfType<X509Certificate>()
                    .First();

                // now, let's set the connection factory's ssl-specific settings
                // NOTE: it's absolutely required that what you set as Ssl.ServerName be
                //       what's on your rabbitmq server's certificate (its CN - common name)
                cf.Ssl.Certs = new X509CertificateCollection(new X509Certificate[] { cert });
                cf.Ssl.ServerName = "rabbitmq-server";
                cf.Ssl.Enabled = true;

                // we're ready to create an SSL connection to the rabbitmq server
                using (IConnection conn = cf.CreateConnection())
                {
                    using (IModel channel = conn.CreateModel())
                    {
                        channel.QueueDeclare("rabbitmq-dotnet-test", false, false, false, null);
                       
                        // create some basic properties for the message we're going to send
                        IBasicProperties props = channel.CreateBasicProperties();
                        props.ContentEncoding = "utf-8";
                        props.MessageId = Guid.NewGuid().ToString();

                        // publish a hello world message
                        channel.BasicPublish("", "rabbitmq-dotnet-test", props, Encoding.UTF8.GetBytes("Hello, World"));

                        // and go get it
                        BasicGetResult result = channel.BasicGet("rabbitmq-dotnet-test", true);

                        if (null == result)
                        {
                            Console.WriteLine("No message received.");
                        }
                        else
                        {
                            Console.WriteLine("-----==<([ Received ])>==-----");
                            DebugUtil.DumpProperties(result, Console.Out, 0);
                        }

                        channel.QueueDelete("rabbitmq-dotnet-test");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}
 And the output:

Using your certificate to authenticate
If you want to authenticate yourself with your certificate as well, you need to change the code and your rabbitmq server's configuration.

First, update your rabbitmq server's configuration.  If you don't know where to look for that, read this page.  Here's what mine looks like:
  [
  {rabbit, [
     {auth_mechanisms,['EXTERNAL']},
     {ssl_listeners, [5671]},
     {ssl_options, [{cacertfile,"C:/Path/To/Your/cacert.pem"},
                    {certfile,"C:/Path/To/Your/cert.pem"},
                    {keyfile,"C:/Path/To/Your/key.pem"},
                    {verify,verify_peer},
                    {fail_if_no_peer_cert,true}]}
   ]}
].
The thing to note there is the addition of {auth_mechanisms,['EXTERNAL']}.  Don't forget to stop your service, re-install it, and start it after making these changes.
rabbitmq-service.bat stop
rabbitmq-service.bat install
rabbitmq-service.bat start
Next, let's update our client code just a tad by setting the connection factory's auth mechanisms.

// we use the rabbit connection factory, just like normal ConnectionFactory cf = new ConnectionFactory();

// set the hostname and the port
cf.HostName = "rabbitmq-server";
cf.Port = AmqpTcpEndpoint.DefaultAmqpSslPort;
cf.AuthMechanisms = new AuthMechanismFactory[] { new ExternalMechanismFactory() };

// I've imported my certificate into my certificate store
// (the Personal/Certificates folder in the certmgr mmc snap-in)
// Let's open that store right now.
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
The other change I made was to insert a Console.ReadLine() just before all of my using () statements cause everything to close down.  By doing this, I can view the RabbitMQ management web app to ensure that I'm authenticating using my certificate.


Wednesday, December 21, 2011

Windows does not always honor DNS order

I was having a problem where some internal server names would become unresolvable after being resolvable.  After becoming tired of flushing the dns resolver cache, I finally opened wireshark to see what was going on.

To my surprise, windows was using my secondary DNS (8.8.8.8) instead of my primary, internal DNS!  After some searching, I finally found this knowledge base article.
This behavior occurs because the Windows XP DNS Client service (Dnscache) follows a certain algorithm when it decides the order in which it uses the DNS servers configured in the TCP/IP properties. If the DNS server list is reprioritized, the Windows XP DNS Client service resets the server priority at periodic intervals. By default, the server priorities are reset every 15 minutes.
 Luckily, the workaround in that same article fixes the issues I was having.
To work around this behavior, modify the registry so that the DNS server that is configured first is tried first on each query. Follow these steps, and then quit Registry Editor:
  1. Click Start, click Run, type regedit, and then click OK.
  2. Locate and then click the following key in the registry:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters
  3. On the Edit menu, point to New, and then click REG_DWORD.
  4. Type ServerPriorityTimeLimit, and then press ENTER.
  5. On the Edit menu, click Modify.
  6. Type 0, and then click OK.
When you set ServerPriorityTimeLimit to 0 (zero), the server priorities are reset before the DNS Client service decides which DNS server to use. You must restart Windows XP for these changes to take affect. Any other value used in this field will cause the default behavior.
Even though this article is for Windows XP, this worked for me on Windows 7.

Sunday, September 18, 2011

Getting Started with Ruby on Rails on Ubuntu 11.04

Recently, my friend Richard has been getting into Ruby. At first, I scoffed, telling Richard that Ruby might be a fine language, but I want nothing to do with the people who write in Ruby.

Remember back in the day when we all read slashdot? Pretty much anyone who admitted to running or even just not hating windows would eventually be set on fire in the comments. I imagine those zealots as the same group that evangelizes Ruby. I'm not alone in thinking this.

The problem, though, is that I'm starting to notice Ruby creeping into my radar more and more. My investigation of node.js made me realize that a lot of the frameworks I like are actually... ports from Ruby. I think technologies like LESS, SASS, and CoffeeScript are pretty cool. And although they're hardly exclusive to Ruby, that's the general direction they're coming from. It's even hard to read about state-of-the-industry testing practices without coming across rspec and cucumber.

Ruby is beginning to remind me of SmallTalk. The language was popular, sure, but what was really appealing was the set of people involved (like Kent Beck, Ward Cunningham, etc) and the concepts that were born from that community. Model-View-Controller. eXtreme Programming (XP). Maybe you've heard of those?

At this point, refusing to take a look at Ruby and learn from the concepts it's birthing would make me one of the snobs I so loathe.

Enough pontification. Let's get to the point - setting up Ruby on Rails on Ubuntu 11.04.

First, start step #2 on this blog: http://blog.zilverline.com/2011/03/28/getting-started-with-ruby-on-rails/. DO NOT install ruby via the ubuntu packages (apt-get). Instead, use RVM, described in step #2.

Once you get to step #6, you're going to hit your next error. Starting the rails server is going to cause this error:
Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs
for a list of available runtimes. (ExecJS::RuntimeUnavailable)
After searching for an hour or so, I finally found this question on stackoverflow. The answer that worked for me was to install node.js. Know how to do that? No problem - just follow these instructions here: http://www.giantflyingsaucer.com/blog/?p=2775.

Once installed, go back and execute 'rails server' and the server will start up! Open http://localhost:3000/ in your browser and you'll see your example rails project!

Have fun!

Tuesday, July 12, 2011

The Case for a Short Bus

We’re building an event-driven architecture (EDA) for our client, so it makes sense that a part of our domain model is going to deal with events. The mountain of concerns associated with moving events around in an EDA is most often handled by an enterprise service bus (ESB). How many concerns, you ask? Just take a look at Wikipedia’s list of “core capabilities” – the ones that “most observers accept” as part of an ESB’s responsibility. There’s a lot going on there! This is why I have a lot of respect for traditional ESBs and the developers who make them.

Unfortunately, in addition to respect, I also have a lot of trepidation when it comes to choosing, installing, configuring, and using an ESB. A lot of the installation and configuration deals with capabilities that I don’t use and the API for those capabilities distracts me from the main use case: creating and consuming events. I wish that traditional ESBs were more like the Spring stack – a set of capabilities that don’t depend on each other, but integrate seamlessly when I want them to.

Another pain point is the mismatch between what existing ESBs offer and what our EDA needs. For example, a benefit of ESBs is the ability to accept events on different types of endpoints (SOAP, REST, FTP, Flat Files, etc). That’s a great selling point if you’re integrating a disparate set of legacy components, but our situation is different. We are writing or integrating every creator and consumer of events, and even if that changes in the future we are in a position to say, “if you want to play with our system, you will do X, Y, and Z.” For us, many capabilities in traditional ESBs add no value.


In addition, there is friction between our team’s goal and an ESB vendor’s goal. ESB vendors make their products generic enough to appeal to many customers; we are fitting generic frameworks to the specific needs of one customer. The level of abstraction in a commercial ESB is likely to be greater than that of a home-brewed counterpart. Keeping with the previous example, “endpoints” are a level of abstraction that is necessary to support the different ways of transporting events. However, if your requirements allow you to take the “opinion” that all components in the architecture will only use AMQP to transport events, your ESB will be less involved – it will be “lighter”. The more “opinions” you can make about your ESB, the “lighter” it will be compared to existing ESB offerings.


Currently, our needs require more than simple publish/subscribe, but less than a full-blown ESB. When we laid out the responsibilities we wanted to assign to our eventing subsystem, we discovered that most responsibilities (like platform-agnostic event serialization and event persistence) already have great frameworks that perform that responsibility (and do little else). That means we won’t have to write everything from scratch; we just have to wire up a few frameworks. Our team considers this to be the best technical solution AND the solution requiring the least amount of effort.


Because it's a smaller bus for our special needs we’ve decided to call this style of ESB a Short Bus. Kudos to Richard for coming up with the name.


In the next few posts, I’m going to lay out the use cases that our Short Bus will have to support and discuss the frameworks we’ve decided to cobble together into a Short Bus.