On Interview Coding Exercises...

03.21.2014 12:35 by kbeckman | Comments

That time of year has come again where my current client has committed to more development work than the existing team can complete by the promised launch date… [Sigh…] We’ve all been there. It’s the unfortunate, situation that occurs when months of work is spent on improper and misguided business priority. Startups and young companies get a pass here because their environment and focus changes rapidly as they’re still trying to figure out what works for their business.

 

But for a lot of companies, inevitably the day comes… SLAP! ..and a new or potential client sets a new priority for your team that has little to do with the focus of prior months. Now the clock is ticking and “we got a long way to go and a short time to get there” because the sales team has already promised a launch date. [beware sarcasm ahead…] So the logical thing to do is throw a lot of money and developers at the problem. With a little luck, pizza and late hours we’ll all be high-fiving this fall when the project is finished.

 

My client is in full-on hiring mode now and we’re getting candidate submissions from Careers 2.0, TopRubyJobs.com and every tech recruiting firm in town. In addition to the standard resume, we’re requiring serious candidates complete a coding exercise for review by the interview team.

 

Over the past couple of weeks, I’ve reviewed well over 20 code submissions. Sometimes the process has been surprisingly pleasant as we’ve seen some exceptional code submissions. Other times it has been pretty painful… Pain is actually a good thing when reviewing code submissions for potential candidates, because it’s not the pain of reviewing bad pull requests for production applications. In end, pull request pain is what we’re trying to avoid. We started requiring the submission of code exercises about 6 months ago and have tweaked the process a bit along the way. We’ve found that with the right approach, code exercises are an invaluable tool to help gauge the eventual code quality of potential candidates. By no means is it fool-proof as I’m sure we’ve passed on some talented developers; but for the most part, the process has worked well. It has been a great tool to see whether or not we want to move forward with the final stages of the interview process and whether or not the potential candidate would work well within the existing codebase.

 

As one of the interviewers, I thought I might pass along a few words of advice to any potential candidates out there. Keep in mind that much of what I say probably applies to code exercises for any development position – not just the openings we’re looking to fill. Additionally, at the end of this post, I mention a few personal take-aways I’ve absorbed from the interview process.

Exercise Guidelines (for context)

Without giving readers the entire example (and without giving any potential candidates a lead on any of the specifics), here’s a quick overview of our coding exercise guidelines. We try to leave the implementation details wide open for interpretation, but steer the candidate in somewhat of a general direction.

 

  • Read a dataset from a provided set of CSV files and perform some calculations.
  • Print your results to STDOUT.
  • The developer is in complete control of what gems they choose to use. …if they choose to use any.
  • There is no database requirement. Use one or don't use one - we don't care. The solution can be completed with or without the use of a database.
  • Approach the problem as if you were intending on deploying this to a production environment.

That’s it!

Take Advantage of the Opportunity

Not everyone has the time or aspires to be an open source contributor or active blogger; and thus, many developers have a pretty lightweight public Github profile. I get it, you use Github for work stuff only – that’s fine. Everyone has different priorities and if you haven’t had the opportunity or the time to put your work on public display, here’s your chance! Treat the exercise as though you actually want others to see it. In this case it’s a significant factor on whether or not we think you’re a good fit for the job.

Write for Production

Coding exercises for interview purposes are more than likely contrived and simplistic, but hopefully it’s fun too. When you’re submitting code, the reviewers are looking to see whether or not it is production quality regardless of what the code is supposed to do. Take some time and put some effort into the solution because code really smells if you don’t. Prove that your solution has evolved a bit over the course of your work – iterate on it. As with any first-pass on code, it could probably use some refactoring. Approach the code in the same way you’d develop a feature for an application you’re working on. 

Source Control

I’m actually a bit surprised that I’m even mentioning this… However, we’ve gotten a lot of submissions through .zip or .tar.gz files. Really?! No one will ever merge something from an archive file into a production codebase. If they do, you’ve just found an organization that should go on your employment blacklist. Submit the code in Github or Bitbucket… Not only does it make the code easier for others to review, but it gives the reviewers some insight into your development approach through the commit history. Additionally, we’ll also be able to tell if you were B.S.-ing about your TDD disciplines.

Tests…

Yes, we’re looking to see if you test your code. If you ever get past a coding exercise to the next round of interviews without writing tests – employer blacklist. On more than one occasion, we’ve seen submissions without tests… Surprisingly, I’m happy to see these because I can automatically dismiss it without any further review. You’ve just made my job easy – and I appreciate that.

Good Tests…

This is without question the most important thing that I’m looking for when reviewing code submissions. I don’t only want to see tests, but thorough and valuable tests. Show clear intent and value in your tests and make sure the tests cover the important areas of your work. Use tests to help you flush out your final solution. It’s extremely important to approach the problem with TDD in mind.

Ruby 1.8.7

Yes, we actually received one solution indicating in the project README that it targeted Ruby 1.8.7. “I haven’t updated my laptop to the newest version yet…” For crying out loud, man! Ruby 1.8.7 hasn’t received bug fixes since June of 2012 and all security fixes stopped almost a year ago (if you don’t believe me, read this). This type of thing is nothing more than developer laziness and suggests you know little or nothing at all about RVM or rbenv. Targeting the latest version of Ruby is nothing more than a quick shell command to set up! Dial 187 on Ruby 1.8.7 and take this as an opportunity to try something new if you haven’t already!

Database Usage

As I mentioned earlier, the coding exercise in our case can be completed without the use of a database; but the decision to do so is left entirely up to the developer. If someone decides to use a database, it’s usually SQLite3 (which is fine because it works everywhere). However, we are going to check to make sure that you’re not specifically targeting SQLite3 because there’s no web project I know of that would use that in production. Use the ActiveRecord ORM and for Pete’s sake, don’t write inline SQL. Yes, we had a submission that had a hard-wired SQLite3 dependency with inline SQL. In my experience, developers (of any language) who think inline SQL is an appropriate practice instead of only-rarely-as-an-exception are cancer to teams. If you don’t believe me, hire one and let me know how that turns out for you. Inline SQL is poor programming practice even if you have tests covering the functionality.

A Rails App? What about STDOUT?

When instructions clearly state to “print all output to STDOUT”, don’t submit a Rails app. Additionally, don’t use “rails new some_application” to generate a project template for the code submission because there’s going to be a lot of unnecessary bloat in your solution… We originally left it up to the developer for the choice of whether or not to write a Rails app, but we’ve since changed the instructions to specifically ask for console output. Previously when Rails apps were submitted, we critiqued the whole project – controllers, models, routes, tests, HTML markup, etc. Now when Rails apps are submitted, it’s painfully clear that the instructions weren’t followed and projects get immediately dismissed. It’s incredibly important to follow the given instructions…

In Closing…

Not only has the code submission and review process been good for our interview process, but it has been good for me as a reviewer… One of the best things you can do for yourself to “level up” as a developer is read, inspect and execute a LOT of code. Over the last several weeks, I’ve done just that.  I’ve seen some approaches to problems that I would never have considered. I’ve learned some Ruby “trick shots” that I’m probably going to use in the future. …and I definitely gained some insight into what others will probably be looking at when the time comes for me to submit my coding exercise.

Asymmetric Encryption - Revisited (in PyCrypto)

02.23.2014 12:33 by kbeckman | Comments

A few months ago, I presented a lightning talk at the monthly Nashville Ruby MeetUp giving an example of asymmetric encryption using the Ruby wrapper for OpenSSL. Today was the first day of the PyTennessee conference in Nashville and I wanted to see if I could translate the example and fill a slot in the lightning talks session. Here goes.

An Example with PyCrypto…

In the eye of the eye Python developer, the following might be a little rough… Before the code below, the only other experience I’ve had with the Python language was earlier today when I was successfully able to print the phrase “Hello, World” to the console output.

 

import Crypto
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Hash import MD5

# Use a larger key length in practice...
KEY_LENGTH = 1024  # Key size (in bits)
random_gen = Random.new().read

# Generate RSA private/public key pairs for both parties...
keypair_snowden = RSA.generate(KEY_LENGTH, random_gen)
keypair_pytn    = RSA.generate(KEY_LENGTH, random_gen)

# Public key export for exchange between parties...
pubkey_snowden  = keypair_snowden.publickey()
pubkey_pytn     = keypair_pytn.publickey()

# Plain text messages...
message_to_snowden  = 'You are a patriot!'
message_to_pytn     = "Russia is really nice this time of year...\nUse encryption and make the NSA CPUs churn and burn!"

# Generate digital signatures using private keys...
hash_of_snowden_message = MD5.new(message_to_snowden).digest()
signature_pytn          = keypair_pytn.sign(hash_of_snowden_message, '')
hash_of_pytn_message    = MD5.new(message_to_pytn).digest()
signature_snowden       = keypair_snowden.sign(hash_of_pytn_message, '')

# Encrypt messages using the other party's public key...
encrypted_for_snowden   = pubkey_snowden.encrypt(message_to_snowden, 32)    #from PyTN
encrypted_for_pytn      = pubkey_pytn.encrypt(message_to_pytn, 32)          #from Snowden

# Decrypt messages using own private keys...
decrypted_snowden   = keypair_snowden.decrypt(encrypted_for_snowden)
decrypted_pytn      = keypair_pytn.decrypt(encrypted_for_pytn)

# Signature validation and console output...
hash_snowden_decrypted = MD5.new(decrypted_snowden).digest()
if pubkey_pytn.verify(hash_snowden_decrypted, signature_pytn):
    print "Edward Snowden received from PyTn:"
    print decrypted_snowden
    print ""

hash_pytn_decrypted = MD5.new(decrypted_pytn).digest()
if pubkey_snowden.verify(hash_pytn_decrypted, signature_snowden):
   print "PyTN received from Edward Snowden:"
   print decrypted_pytn

Resources

Ruby LDAP Membership Query

01.20.2014 15:15 by kbeckman | Comments

Omniauth is easily one of the most often used Ruby gems in my toolset. Recently, I needed to use an Omniauth plugin that I haven’t used before – omniauth-ldap. Getting omniauth-ldap setup and configured was relatively straightforward; and as advertised, it provided authentication via LDAP query against the organization’s domain controller.

 

Unfortunately (and a bit unexpectedly) though, the contents of the Omniauth authentication hash didn’t contain a list of groups the user belonged to – a requirement for our authentication strategy. The applications I’m working need to translate a given user’s LDAP group membership(s) into application roles for authorization purposes. So as it turns out, after the initial LDAP call for authentication (via omniauth-ldap), I needed to make an additional query against the LDAP provider to get a list of the user’s memberships to parse and convert to application roles.

 

Here’s the short Ruby shell script I whipped up to test making an additional LDAP query for user memberships before I built a few classes and actually integrated it into the application. The @ldap_settings[:auth] hash are the account details used to connect and issue the LDAP query. The values of @ldap_settings and @base will change for your environment (I removed the actual values in this example).

 

#!/usr/bin/env ruby

require 'net/ldap'
require 'pry'

class MembershipQuery

  def initialize
    @ldap_settings = {
        :host => 'ldap-server',
        :auth => {
            :method   => :simple,
            :username => 'CN=Ldap Auth,OU=Authentication,OU=Service Accounts,DC=YOURDOMAIN',
            :password => 'password'
        }
    }

    @base = 'DC=YOURDOMAIN'
  end

  def query(username)
    result  = nil
    ldap    = Net::LDAP.new(@ldap_settings)
    filter  = "(&(objectClass=user)(sAMAccountName=#{username}))"

    if ldap.bind

      ldap.search(:base => @base, :filter => filter) do |object|
        result = object.memberof
      end
    else
      raise 'Authentication Error!'
    end

    result
  end

end

puts MembershipQuery.new().query('Ric_Flair')

Comments are Back!

01.20.2014 14:10 by kbeckman | Comments

I’ve had blog comments turned off for a some time now because this site has been hammered by comment SPAM bots. And admittedly, I got sick and tired of monitoring all of the garbage on a daily basis.

 

Today, I’m happy to announce that comments are back! I’ve wired up Disqus and thanks to a migration tool from Rob Ellison out on the West Coast, I was able to migrate all of the existing comments without having to spend any time parsing and transforming XML. If you notice any display issues or any other issues, please let me know…

I’m looking forward to hearing from you [again]…

A Quick Intro to OpenSSL Asymmetric Encryption

10.03.2013 05:16 by kbeckman | Comments

This post is my summary of the lightning talk for tonight’s Ruby Meetup in Nashville. I should have known that I’d need a bit more than five minutes to cover an intro to OpenSSL asymmetric encryption… Thank goodness for blogs! In the spirit of a lightning talk, I’ll keep this short an cover only the high-level points of this topic.

 

A Quick Primer…

Asymmetric cryptography is important in a number of applications and protocols that we use every day and it’s beneficial for software developers to know at least a little bit about the topic. Let’s start with a quick definition… Asymmetric cryptography is a type of cryptographic algorithm that utilizes private/public key pairs for encrypting data. In simplistic terms, data encrypted with a public key may only be decrypted with its corresponding private key and data signed with a private key can be verified with its corresponding public key.

 

One important use for asymmetric cryptography is for the generation of “digital signatures”. Digital signatures are useful for verifying the identity behind an email message or authentication token (SAML tokens anyone?). Digital signatures are also used to verify the authenticity of software packages. To generate a digital signature, an entity will generate an encrypted hash [serving as the “signature”] based on a digest algorithm (message digest) and some message content (i.e. an email message) using their private key. The message is then sent to a third party along with its digital signature. To verify authenticity of the original message, a third party verifies the encrypted signature hash by using the sender’s public key to decrypt the signature hash and compares the decrypted contents with its own hash of the original message content. If the message hashes match, the message is said to be authentic. If the hashes do not match, the message has been tampered with in some way before it was received.

 

Taking this a step further, asymmetric cryptography is also used to encrypt the contents of messages. Building on the example above, two parties can send secure messages to each other provided that they first share their public keys. Party X can secure a message for Party Y by encrypting a message using Party Y’s public key. Since the only key able to decrypt the data is Party Y’s private key, the message is unreadable to anyone other than Party Y.

 

Unfortunately, asymmetric encryption is an extremely slow method of encryption – much slower than symmetric encryption algorithms that use a single key (i.e Advanced Encryption Standard or AES). Web browsers use a combination of asymmetric and symmetric encryption to enforce the SSL/TLS protocols for secure web sites. In this scenario, the web server and browser use asymmetric encryption negotiate a secure key using the website’s SSL certificate and client machine’s security certificate. The negotiated message/key is then used as the encryption key for continued communication using faster symmetric encryption.

The Code…

This code snippet is a trivial example whereas a single Ruby shell script simulates secure communication between the Nashville Ruby Meetup Group and our favorite patriot, Edward Snowden.  The script generates an RSA private/public key pair for each party; exports the public key (to provide to the other party); encrypts a message for each party using the other’s public key; and decrypts the message using each party’s own private key. Additionally, I added message signing and verification to this snippet (although it was not part of my original lightning talk code sample).

 

#!/usr/bin/env ruby

require 'openssl'

KEY_LENGTH      = 4096  # Key size (in bits)
digest_fuction  = OpenSSL::Digest::SHA256.new # Predetermined signature digest function


# Generate RSA private/public key pairs for both parties...
keypair_snowden = OpenSSL::PKey::RSA.new(KEY_LENGTH)
keypair_meetup  = OpenSSL::PKey::RSA.new(KEY_LENGTH)

# Public key export for exchange between parties...
pubkey_snowden  = OpenSSL::PKey::RSA.new(keypair_snowden.public_key.to_der)
pubkey_meetup   = OpenSSL::PKey::RSA.new(keypair_meetup.public_key.to_der)

# Plain text messages...
message_to_snowden  = 'You are a patriot!'
message_to_meetup   = "Russia is really nice this time of year...\nUse encryption and make the NSA CPUs churn and burn!"

# Generate digital signatures using private keys...
signature_meetup  = keypair_meetup.sign(digest_fuction, message_to_snowden)
signature_snowden = keypair_snowden.sign(digest_fuction, message_to_meetup)

# Encrypt messages using the other party's public key...
encrypted_for_snowden = pubkey_snowden.public_encrypt(message_to_snowden) #from Meetup
encrypted_for_meetup  = pubkey_meetup.public_encrypt(message_to_meetup)   #from Snowden

# Decrypt messages using own private keys...
decrypted_snowden = keypair_snowden.private_decrypt(encrypted_for_snowden)
decrypted_meetup  = keypair_meetup.private_decrypt(encrypted_for_meetup)


# Signature validation and console output...
if pubkey_meetup.verify(digest_fuction, signature_meetup, decrypted_snowden)
  puts "Edward Snowden received from Ruby Meetup:"
  puts "\"#{message_to_snowden}\"\n\n"
end

if pubkey_snowden.verify(digest_fuction, signature_snowden, decrypted_meetup)
  puts "Ruby Meetup received from Edward Snowden:"
  puts "\"#{message_to_meetup}\""
end

Why is this Important?

I’m sure by this point, you’re no stranger to the countless news reports of  domestic NSA spying. The NSA is capable of seeing  just about everything on the Internet including your personal emails regardless of constitutionality or legality. There are also a large number of American organizations, who either by their own will or by NSA influence, provide the NSA with what is essentially an open, unencrypted pipeline to all of your online data. These organizations bypass encryption or provide your data before it has the chance to be encrypted. If that doesn’t scare you, it should… The only way you can ensure the security of your data and your messages is to encrypt that data personally before it’s transmitted over the wire. …and the intent of this post was to show you how that can be done. There’s no guarantee that the NSA won’t eventually be able to decrypt the encrypted messages you send. However, you can and should slow them down a bit by making their servers work a lot harder to get at your personal information. I’m an honest, law-abiding citizen who pays taxes every April 15th and will do so until the day I die. If the NSA choses to read my personal emails to my wife, invoices I send to my clients or anything else that’s either none of their business or NOT a threat to the national security of the United States, then they’re going to have to waste some CPU cycles doing so.

 

One Last Comment…

Check out GPG Tools. It’s an open-source encryption suite that plugs in to Apple Mail allowing you to sign and encrypt emails using asymmetric encryption. It allows you to create keys with a maximum of 4096 bits and according to the algorithm estimates on keylength.com, there’s a good chance it would take the NSA a while to crack your encryption.