andrewmccall.com http://andrewmccall.com Most recent posts at andrewmccall.com posterous.com Wed, 11 Jan 2012 11:11:26 -0800 Customer support, what a joke. http://andrewmccall.com/customer-support-what-a-joke http://andrewmccall.com/customer-support-what-a-joke
Sainsbury's online grocery site was broken last night; it kept giving me 404 errors when I tried to pay for my order. There was one slot left that would get here before I had to pick the kids up, I'd booked it and wanted to keep it,  so I emailed their customer support. I was hoping maybe they'd tell me when it would be fixed, reserve the slot for me or something. 

I kept checking my email and trying their site and eventually later in the evening it worked, so I forgot about the whole thing until this morning when I got this: 

From: "Sainsbury's Online " <sainsburys@mailuk.custhelp.com>
Subject: Shopping online [Reference: 120110-00XXXX]
Date: 11 January 2012 09:54:42 GMT
Reply-To: "Sainsbury's Online " <sainsburys@mailuk.custhelp.com>

Dear Mr McCall

Thank you for your email about our website. I'm sorry you've been having problems on our website due to an error 404 message. I understand this must be frustrating.

I've spoke to our Customer Support Team and they have told me that Microsoft have been experiencing issues accessing the Sainsbury's servers that our website is based upon. They suggest that you search Google for "Error 404 Fix" and a Microsoft Tool will be available for download. Once downloaded this tool will fix the error and you'll be able to use our website again.

If you need any further help please contact us on 0800 328 1700. One of my colleagues will be happy to assist you.

We appreciate you taking the time to contact us and hope this issue is resolved for you soon.

Kind regards

<Name Removed>
Customer Manager
Sainsbury's Online
onlineservice@sainsburys.co.uk


I don't know what I can add to that. 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Thu, 23 Dec 2010 14:09:01 -0800 Validation 1.0.0 released. http://andrewmccall.com/validation-100-released http://andrewmccall.com/validation-100-released I just pushed my little JSR-303 validation lib out as a 1.0.0 release. The JSR-303 is not 1.0 so it seemed like a good idea. 

The biggest changes are probably the ones needed to support those. If you were using the library you won't notice any difference, the changes are all internal and the actual annotations haven't changed. 

I've also removed the springframework package. JSR-303 is now supported in spring 3 and their support is better.

Finally I've added some static methods to AbstractAnnotationTest, assertValid and assertViolation; I've found them useful testing annotated classes and figure someone else may too. 

Check it out and let me know what you think. 

http://github.com/andrewmccall/validation

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Thu, 16 Dec 2010 11:23:56 -0800 oEmbed http://andrewmccall.com/oembed http://andrewmccall.com/oembed I came across oEmbed the other day, completely by accident.

I've been working on a couple of projects in my free time and in a few of them I really wanted to be able to embed better information about a URL, if it existed. I'd been working up my own rough JSON schema that was in many ways similar to oEmbed.

Then I came across a tweet that mentioned embed.ly and oEmbed and embed.ly are the perfect solution. Instead of rolling my own service I'm integrating theirs.

At it's most basic it's a standard way of getting more than just a link you can embed in your site and provides a standard interface for doing it across the web. 

If you're looking to embed things in your website, take a look. There are plugins available for wordpress and others as well as a jQuery plugin you can use pretty much anywhere. 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Wed, 15 Dec 2010 13:21:00 -0800 Even more secure passwords. http://andrewmccall.com/even-more-secure-passwords http://andrewmccall.com/even-more-secure-passwords

A few days ago I posted suggesting that you salt your passwords, I'm back armed with even more knowledge and better advice. Turns out the relative strengths of one hashing algorithm vs another can in fact make a difference, in a way I didn't even consider - their speed. 

Most crypto hash functions are designed for speed, you want to be able to compute the hashes of lots of data pretty quickly if your pushing it down the wire. That speed works in an attackers favour if they're brute forcing a list of passwords and newer hashing functions can make it worse, one of the requirements for SHA-3 is that it's faster than the SHA-2 family. 

So what's the new right answer? 

Choose a function that takes enough time that an attacker has to work for each and every password - ideally long enough that it would take forever to crack just one - while making sure that legitimate users aren't waiting forever while you check their passwords. 

There are two ways of doing this, run a fast hash function many times or deliberately pick a slow hash function.

Running many iterations of a fast hashing algorithm is pretty self explanatory, run it twice and it takes twice as long, run it a thousand times and it takes a thousand times as long to attack each password.

Bcrypt is an example of the second, based on the blowfish algorithm it uses the fact that the key setup step is a relatively expensive operation and difficult to optimise. By making use of this bcrypt allows you to set a work factor and creates a hashing algorithm that is expensive and also difficult to optimise. 

Which is better? I have no idea, both are widely used and it really depends on your environment. I'd love to hear what others think though.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Tue, 14 Dec 2010 04:17:56 -0800 Chrome OS. http://andrewmccall.com/chrome-os http://andrewmccall.com/chrome-os I don't think Chrome OS is going to be a success.

It's perfect for Google, shows that all you really need is a browser and does it in a compelling way. But it's not going to be a success and I'll cast my lot in with those that predict that it'll get rolled into Android.
The reason I don't see it working is that Google won't use it. Google is a company of engineers, developers and hackers - what do they want with a computer they can't use to do that?
The Chrome OS team is designing and building a product for someone else. Taking things away is a great thing, look at Apple, but if you take so much away that it becomes a product for someone else and you're no longer eating your own dog food. That doesn't usually work out well.

I may be wrong, maybe the team is great and maybe they can overcome the obstacles, but I'll put my money on the best that will come of Chrome OS is that it's evolved into another product or as many are predicting, rolled into Android.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Mon, 13 Dec 2010 07:22:00 -0800 Salt your passwords. http://andrewmccall.com/salt-your-passwords http://andrewmccall.com/salt-your-passwords

Gawker media is the latest in a long list of compromised systems that have exposed user passwords. Unlike when it happened to the ASF a few months ago, I'm unaffected.

Forbes and others are banging on about weak encryption being the problem, it's not. Passwords aren't encrypted generally, they're passed through a one way hash function. You can't undo the hash, so you can't decrypt the passwords. When you hash the same value though it will always produce the same hash - so you can ask a user for their password, hash the value they enter and check that against the hash you've stored.

The relative strengths of one hash function vs another actually makes very little difference when it comes to passwords. As long as it's collision free for the set of possible passwords, which almost all will be, they're really strong enough no matter how old they are. 

Gawker made a basic mistake that even the most advanced algorithm wouldn't help, they're not salting their passwords. 


Cracking hashed passwords involves computing the hashes until you create the same hashed value. You run the algorithm across a list of know common passwords, dictionary words and common variations. The same value will always produce the same hash, so everyone who uses the same password will also always have the same hash. You just need to compute all the common/obvious ones and look at all the users to find the ones with that match your list. Lots of those users will probably be using their password for email and other services too... oops.

Salting adds something unique to a user, say their email address or ID, forcing an attacker to compute every possible password for each user individually.  Even if two users have chosen the same password they will have a different hash. The better the salt you can choose, the more work an attacker has to do to get passwords.

It's not a panacea though, you've still exposed their details and given enough time a determined attacker can and will be able to recover every last password. What it gives you is time to disclose the breach and your users time to change their passwords on other services which may be the same.

UPDATE: I've added a new post with some more thoughts, clarifications and corrections here

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Sat, 13 Nov 2010 15:48:12 -0800 Maven and self signed client certs. http://andrewmccall.com/maven-and-self-signed-client-certs http://andrewmccall.com/maven-and-self-signed-client-certs I've been using a self-signed client certificate on my development server. Today working on my OAuth lib I started getting problems connecting to twitter, failed SSH handshakes. With a message something like: 

Connection has been shutdown: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

It's because in my maven command I'm using a custom truststore which doesn't have any of the default root certificates in it, just mine. Running this command imported the default roots into the truststore I've been using with maven: 

keytool -importkeystore -srckeystore $JAVA_HOME/lib/security/cacerts -destkeystore ./trust.jks

I got a long list of  Entry for alias keychainrootca-xx successfully imported and now everything works as it should. 

Hope it helps. 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Sat, 13 Nov 2010 03:38:54 -0800 Git checkout a tag. http://andrewmccall.com/git-checkout-a-tag http://andrewmccall.com/git-checkout-a-tag When I recently rebuilt my development server using Puppet I decided not to backup my nexus repository since there were all of three files I'd built in there. Today I wanted to start recreating them and couldn't find out how to checkout a git tag. 

A couple of google searches weren't terrible successful and it's something that's not really explained well so here it is. 

To checkout a tag you just have to 
git checkout <TAG_NAME>

Yes it's that simple. 

You'll probably get the same warning message telling you you're in a detached HEAD state. If you intended to do some work here it's probably a really good idea to take the advice the message gives you and create a branch. You could do that when you checkout by adding -b

git checkout <TAG_NAME> -b <BRANCH_NAME>

I didn't want to do anything except a mvn clean deploy to get my library deployed back to nexus, then get back to where I was. So I didn't. 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Tue, 21 Sep 2010 13:13:26 -0700 Giving Posterous a shot. http://andrewmccall.com/giving-posterous-a-shot http://andrewmccall.com/giving-posterous-a-shot I've been using wordpress for a few years on andrewmccall.com and it's served me well but I hear good things about  posterous and decided to give it a try. 

This is that try, and so far I like it. Think I'll repoint the domain. 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Tue, 17 Aug 2010 20:56:42 -0700 Multiple users, same key in puppet. http://andrewmccall.com/2010/08/688 http://andrewmccall.com/2010/08/688 I've been a bit quiet on the server front and to be honest a bit stuck. I'm new to Puppet and it took me a while to figure out how to get users working the way I wanted them to. Sleeping on it and reading some more and eventually I got there. I also have a day job to hold down and a family to entertain on the weekend, so as much as I really wanted to get this done life got in the way. My goal now is to get my repositories back online and to create a new one and start committing this Puppet config I've been building somewhere. I decided I'd go with Git for my main projects, the ones that had graduated out of the sandbox but that the sandbox would keep running subversion. I've also planned to run them both via SSH to lower the ports I open and to stick with the same key infrastructure I was building to access everything else. The only problem I had was that I couldn't figure out how to use the same key in multiple places with the otherwise good ssh::auth module from the Puppet patterns wiki. And I wasn't the only one, even the module author thought it was a good idea but difficult to implement. After working on it a few evenings I eventually learned enough about puppet to have a crack at it myself- it may no be the most elegant solution, but it seems to work. I allowed root to login via ssh and turned password authentication on while I did this - I didn't want to lock myself out of my server if I made a mistake. You may want to do the same, or you may not. It's up to you. If you do undo the edits you made to your sshd_config a few days ago In the most simple terms I added a parameter $key throughout ssh::auth which when present indicated you're using a different key, not the one normally used in title.
modules/user/manifests/auth.pp
# =========                                                 
# ssh::auth                                                 
# =========                                                 
#                                                           
# The latest official release and documentation for ssh::auth can always
# be found at http://reductivelabs.com/trac/puppet/wiki/Recipes/ModuleSSHAuth .
#                                                                              
# Version:          0.3.2                                                      
# Release date:     2009-12-29                                                 

class ssh::auth {

$keymaster_storage = "/var/lib/keys" 

Exec { path => "/usr/bin:/usr/sbin:/bin:/sbin" }
Notify { withpath => false }                    


##########################################################################


# ssh::auth::key 

# Declare keys.  The approach here is just to define a bunch of
# virtual resources, representing key files on the keymaster, client,
# and server.  The virtual keys are then realized by                 
# ssh::auth::{keymaster,client,server}, respectively.  The reason for
# doing things that way is that it makes ssh::auth::key into a "one  
# stop shop" where users can declare their keys with all of their    
# parameters, whether those parameters apply to the keymaster, server,
# or client.  The real work of creating, installing, and removing keys
# is done in the private definitions called by the virtual resources: 
# ssh_auth_key_{master,server,client}.                                

define key ($ensure = "present", $filename = "", $force = false, $group = "puppet", $home = "", $keytype = "rsa", $length = 2048, $maxdays = "", $mindate = "", $options = "", $user = "", $key = "") {                                                                                                                                                    

  ssh_auth_key_namecheck { "${title}-title": parm => "title", value => $title }

  # apply defaults
  $_filename = $filename ? { "" => "id_${keytype}", default => $filename }
  $_length = $keytype ? { "rsa" => $length, "dsa" => 1024 }               
  $_user = $user ? {                                                      
    ""      => regsubst($title, '^([^@]*)@?.*$', '\1'),                   
    default => $user,                                                     
  }                                                                       
  $_home = $home ? { "" => "/home/$_user",  default => $home }            

  ssh_auth_key_namecheck { "${title}-filename": parm => "filename", value => $_filename }

  @ssh_auth_key_master { $title:
    ensure  => $ensure,         
    force   => $force,          
    keytype => $keytype,        
    length  => $_length,        
    maxdays => $maxdays,        
    mindate => $mindate,        
  }                             
  @ssh_auth_key_client { $title:
    ensure   => $ensure,        
    filename => $_filename,     
    group    => $group,         
    home     => $_home,         
    user     => $_user,         
  }                             
  @ssh_auth_key_server { $title:
    ensure  => $ensure,         
    group   => $group,          
    home    => $_home,          
    options => $options,        
    user    => $_user,  
    key                => $key,        
  }                             
}                               


##########################################################################


# ssh::auth::keymaster
#                     
# Keymaster host:     
# Create key storage; create, regenerate, and remove key pairs

class keymaster {

  # Set up key storage

  file { $ssh::auth::keymaster_storage:
    ensure => directory,               
    owner  => puppet,                  
    group  => puppet,                  
    mode   => 644,                     
  }                                    
                                       
  # Realize all virtual master keys    
  Ssh_auth_key_master             

} # class keymaster


##########################################################################


# ssh::auth::client
#                  
# Install generated key pairs onto clients

define client ($ensure = "", $filename = "", $group = "", $home = "", $user = "") {

  # Realize the virtual client keys.
  # Override the defaults set in ssh::auth::key, as needed.
  if $ensure   { Ssh_auth_key_client  { ensure   => $ensure   } }
  if $filename { Ssh_auth_key_client  { filename => $filename } }
  if $group    { Ssh_auth_key_client  { group    => $group    } }

  if $user { Ssh_auth_key_client  { user => $user, home => "/home/$user" } }
  if $home { Ssh_auth_key_client  { home => $home } }                       
  if $key { Ssh_auth_key_client  { key => $key } }

  realize Ssh_auth_key_client[$title]

} # define client


##########################################################################


# ssh::auth::server
#                  
# Install public keys onto clients

define server ($ensure = "", $group = "", $home = "", $options = "", $user = "", $key="") {

  # Realize the virtual server keys.
  # Override the defaults set in ssh::auth::key, as needed.
  if $ensure  { Ssh_auth_key_server  { ensure  => $ensure  } }
  if $group   { Ssh_auth_key_server  { group   => $group   } }
  if $options { Ssh_auth_key_server  { options => $options } }

  if $user { Ssh_auth_key_server  { user => $user, home => "/home/$user" } }
  if $home { Ssh_auth_key_server  { home => $home } }  
  if $key  { Ssh_auth_key_server  { key => $key } }
                       

  realize Ssh_auth_key_server[$title]

} # define server

} # class ssh::auth


##########################################################################


# ssh_auth_key_master
#                    
# Create/regenerate/remove a key pair on the keymaster.
# This definition is private, i.e. it is not intended to be called directly by users.
# ssh::auth::key calls it to create virtual keys, which are realized in ssh::auth::keymaster.

define ssh_auth_key_master ($ensure, $force, $keytype, $length, $maxdays, $mindate) {

  Exec { path => "/usr/bin:/usr/sbin:/bin:/sbin" }
  File {                                          
    owner => puppet,                              
    group => puppet,                              
    mode  => 600,                                 
  }                                               

  $keydir = "${ssh::auth::keymaster_storage}/${title}"
  $keyfile = "${keydir}/key"                          

  file { 
    "$keydir":
      ensure => directory,
      mode   => 644;      
    "$keyfile":           
      ensure => $ensure;  
    "${keyfile}.pub":     
      ensure => $ensure,  
      mode   => 644;      
  }                       

  if $ensure == "present" {

    # Remove the existing key pair, if
    # * $force is true, or            
    # * $maxdays or $mindate criteria aren't met, or
    # * $keytype or $length have changed            

    $keycontent = file("${keyfile}.pub", "/dev/null")
    if $keycontent {                                 

      if $force {
        $reason = "force=true"
      }                       
      if !$reason and $mindate and generate("/usr/bin/find", $keyfile, "!", "-newermt", "${mindate}") {
        $reason = "created before ${mindate}"                                                          
      }                                                                                                
      if !$reason and $maxdays and generate("/usr/bin/find", $keyfile, "-mtime", "+${maxdays}") {      
        $reason = "older than ${maxdays} days"                                                         
      }                                                                                                
      if !$reason and $keycontent =~ /^ssh-... [^ ]+ (...) (\d+)$/ {                                   
        if       $keytype != $1 { $reason = "keytype changed: $1 -> $keytype" }                        
        else { if $length != $2 { $reason = "length changed: $2 -> $length" } }                        
      }                                                                                                
      if $reason {                                                                                     
        exec { "Revoke previous key ${title}: ${reason}":                                              
          command => "rm $keyfile ${keyfile}.pub",                                                     
          before  => Exec["Create key $title: $keytype, $length bits"],                                
        }                                                                                              
      }                                                                                                
    }                                                                                                  

    # Create the key pair.
    # We "repurpose" the comment field in public keys on the keymaster to
    # store data about the key, i.e. $keytype and $length.  This avoids  
    # having to rerun ssh-keygen -l on every key at every run to determine
    # the key length.                                                     
    exec { "Create key $title: $keytype, $length bits":                   
      command => "ssh-keygen -t ${keytype} -b ${length} -f ${keyfile} -C \"${keytype} ${length}\" -N \"\"",
      user    => "puppet",                                                                                 
      group   => "puppet",                                                                                 
      creates => $keyfile,                                                                                 
      require => File[$keydir],                                                                            
      before  => File[$keyfile, "${keyfile}.pub"],                                                         
    }                                                                                                      

  } # if $ensure  == "present"

} # define ssh_auth_key_master


##########################################################################


# ssh_auth_key_client
#                    
# Install a key pair into a user's account.
# This definition is private, i.e. it is not intended to be called directly by users.

define ssh_auth_key_client ($ensure, $filename, $group, $home, $user) {

  File {
    owner   => $user,
    group   => $group,
    mode    => 600,   
    require => [ User[$user], File[$home]],
  }                                                    

  $key_src_file = "${ssh::auth::keymaster_storage}/${title}/key" # on the keymaster
  $key_tgt_file = "${home}/.ssh/${filename}" # on the client                       

  $key_src_content_pub = file("${key_src_file}.pub", "/dev/null")
  if $ensure == "absent" or $key_src_content_pub =~ /^(ssh-...) ([^ ]+)/ {
    $keytype = $1                                                         
    $modulus = $2                                                         
    file {                                                                
      $key_tgt_file:                                                      
        ensure  => $ensure,                                               
        content => file($key_src_file, "/dev/null");                      
      "${key_tgt_file}.pub":                                              
        ensure  => $ensure,                                               
        content => "$keytype $modulus $title\n",                          
        mode    => 644;                                                   
    }                                                                     
  } else {                                                                
    notify { "Private key file $key_src_file for key $title not found on keymaster; skipping ensure => present": }
  }                                                                                                               

} # define ssh_auth_key_client


##########################################################################


# ssh_auth_key_server
#                    
# Install a public key into a server user's authorized_keys(5) file.
# This definition is private, i.e. it is not intended to be called directly by users.

define ssh_auth_key_server ($ensure, $group, $home, $options, $user, $key) {

  # on the keymaster:
  $key_src_dir = "${ssh::auth::keymaster_storage}/${key}"
  $key_src_file = "${key_src_dir}/key.pub"                 
  # on the server:                                         
  $key_tgt_file = "${home}/.ssh/authorized_keys"           
                                                           
  File {                                                   
    owner   => $user,                                      
    group   => $group,                                     
    require => User[$user],                                
    mode    => 600,                                        
  }                                                        
  Ssh_authorized_key {                                     
    user   => $user,                                       
    target => $key_tgt_file,                               
  }                                                        

  if $ensure == "absent" {
    ssh_authorized_key { $title: ensure => "absent" }
  }                                                  
  else {
    $key_src_content = file($key_src_file, "/dev/null")
    if ! $key_src_content {
      notify { "Public key file $key_src_file for key $_key not found on keymaster; skipping ensure => present": }
    } else { if $ensure == "present" and $key_src_content !~ /^(ssh-...) ([^ ]*)/ {
      err("Can't parse public key file $key_src_file")
      notify { "Can't parse public key file $key_src_file for key $_key on the keymaster: skipping ensure => $ensure": }
    } else {
      $keytype = $1
      $modulus = $2
      ssh_authorized_key { $title:
        ensure  => "present",
        type    => $keytype,
        key     => $modulus,
        options => $options ? { "" => undef, default => $options },
      }
    }} # if ... else ... else
  } # if ... else

} # define ssh_auth_key_server


##########################################################################


# ssh_auth_key_namecheck
#
# Check a name (e.g. key title or filename) for the allowed form

define ssh_auth_key_namecheck ($parm, $value) {
  if $value !~ /^[A-Za-z0-9]/ {
    fail("ssh::auth::key: $parm '$value' not allowed: must begin with a letter or digit")
  }
  if $value !~ /^[A-Za-z0-9_.:@-]+$/ {
    fail("ssh::auth::key: $parm '$value' not allowed: may only contain the characters A-Za-z0-9_.:@-")
  }
} # define namecheck
I won't go through all the changes line by line, the important things to note are that I added the variable $key and limited the ssh_auth_key_master automatic realisation to only calls that have not provided a key. Basically if you give it a key you're trying to use an exisiting key, otherwise you're looking to create a new key for a user.

Usage

Using the new calls is easy. Assuming you've cerated your user addding the following lines will allow the previously created andrewmccall key to login as root:
manifests/nodes.pp
node build {
    include sudo, user, sshd, ssh::auth, user::keystore, repos
    user::create{"andrewmccall": groups => "sudo"}
    user::client_key{"andrewmccall":}
    user::server_key{"andrewmccall":}

    ssh::auth::key{"andrewmccall-root": key=>"andrewmccall"}
    ssh::auth::server{"andrewmccall-root": key=>"andrewmccall", user=>"root", home=>"/root"}
}
In lines 7 & 8 you can see I use the andrewmccall key to allow logins as root. Apologies for the brevity of the post, I guess you can probably tell I'm sick of looking at this code. If you do have any questions or there is any interest in it I'll elaborate in the comments or a future post.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Wed, 11 Aug 2010 21:22:23 -0700 Restrict access in Puppet – part 2 http://andrewmccall.com/2010/08/restrict-access-in-puppet-%e2%80%93-part-2 http://andrewmccall.com/2010/08/restrict-access-in-puppet-%e2%80%93-part-2 Yesterday we got the key creation working, today we'll lock the server down properly by preventing root login and adding a user to the sudoers file. Let's start with the latter.

Sudoers

First we need a group of administrators, for the sake of ease and self-documentation I called it sudo. Well ubuntu called it sudo, but we still need to ensure it exists, because it won't on all operating systems.
modules/sudo/manifests/init.pp
import "*"
class sudo {
    include sudo::install, sudo::sudoers
    group{"sudo": ensure => "present"}
}
All we did here was very simply ensure that the puppet group existed. Next we need to update our sudoers file to allow members of the sudo group to sudo.
modules/sudo/files/sudoers
# /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
#

Defaults        env_reset

# Uncomment to allow members of group sudo to not need a password
# %sudo ALL=NOPASSWD: ALL

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root        ALL=(ALL) ALL
%sudo   ALL=(ALL) ALL
All we did here was add the last line which allows members of the sudo group to do everything. We do require a user's password. The next and final step is to ensure our user module allows us to specify additional groups.
modules/user/manifests/init.pp
import "*"
class user {

    define create ($groups = "") {
        group{$title: ensure => "present"}         
        user { "$title":
            ensure  => "present",
            gid   => "$title",
            groups => $groups,
            home    => "/home/$title",
            shell   => "/bin/bash",
            managehome => true,
            require => [Group["$title"]],
        }
        file { "/home/$title":
            ensure => "directory",
            mode   => 700,
            owner  => "$title",
            group  => "$title",
        }
        file { "/home/$title/.ssh":
            ensure => "directory",
            mode   => 600,
            owner  => "$title",
            group  => "$title",
        }
        ssh::auth::key{"$title":}
    }
    define client_key ($ensure = "", $filename = "") {
        ssh::auth::client{"$title": ensure=>$ensure, filename=>$filename}
    }
    define server_key ($ensure = "", $user = "") {
        ssh::auth::server{"$title": ensure=>$ensure, user=>$user}
    }
}
On line 4 I added a parameter $groups which defaults to empty and on line 9 I pass that parameter into the user creation step. There you have it, run puppet and your user will get added to the sudo group and should be able to sudo themselves up a sandwich.

sshd

The next step in securing our server is to prevent logins with passwords and prevent root logins. I can't stress enough how important it is here that you test you can login with your key and that you can sudo or at least you know your root password. If you go ahead without being able to do these things you may be left unable to login to your machine. Our sshd module is a lot like the original sudoers module. We're simply copying a file into /etc. Start by creating our module directories
# mkdir -p modules/sshd/files modules/sshd/manifests
Next we create the init.pp file for the ssh module. I've taken inspiration from the example on the puppet wiki
modules/sshd/manifests/init.pp
class sshd {

   package {"openssh-server": ensure=> "installed"}

    file { "/etc/ssh/sshd_config":
        owner => "root",
        mode => 644,
        notify => Service["ssh"],
        require => Package["openssh-server"],
        source => 
            "puppet:///modules/sshd/sshd_config"
    }

    service { "ssh":
        enable => true,
        ensure => running,
        require => [
            File["/etc/ssh/sshd_config"],
            Package["openssh-server"]
        ]
    }
}
Next copy your current sshd_config into the files directory of your module
# cp /etc/ssh/sshd_config modules/sshd/files
Then I edited the following lines to deny root logins and password authentication:
modules/sshd/files/sshd_config
PermitRootLogin no
...
PasswordAuthentication no
Finally I updated my node.pp to include the new module
manifests/nodes.pp
node build {
    include sudo, user, sshd, ssh::auth, user::keystore
    user::create{"andrewmccall": groups => "sudo"}
    user::client_key{"andrewmccall":}
    user::server_key{"andrewmccall":}
}
Execute puppet and your sshd_config should now be properly set.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Tue, 10 Aug 2010 21:10:12 -0700 Restrict access in Puppet - part 1 http://andrewmccall.com/2010/08/restrict-access-in-puppet-part-1 http://andrewmccall.com/2010/08/restrict-access-in-puppet-part-1 This time we're going to lock the server down a bit with Puppet. Now that we have our own user, let's force login using a public key we'll create for the user. Eventually I also want to create a self signed certificate for the user to use with their public key to access resources via HTTPS with client certificates wrap the whole certificate up in a pkcs12 file and email it to them. I won't get into that yet. I was going to write the framework myself, even had a skeleton all laid out - I'd decided on two classes, the keystore which would handle creating, storing and revoking keys and later certificates and a user class for creating users.
  • create <user> creates a new user with the given username.
  • clientkey <user> [filename] installs the key for a given user, optionally set a filename. I already have some keys
  • serverkey <user> [login_as] installs the key into the authorized_keys allowing users to login to this server. Defaults to logging in as the same user as the key 'owner' if the. I also need to use my key to login as another user, the git and svn users for example.
Then I found the ssh::auth from the puppet wiki. it's released under the GPL, while everything else I write is Apache 2 compatible - if that's a problem you may want to stop here and look for another solution. If you find one that's Apache 2 compatible, I'd love to know about it. For what I'm doing it doesn't really matter, I went with my skeleton package as a thin wrapper around it and downloaded the module into my users package.
# wget http://projects.reductivelabs.com/attachments/download/935/auth.pp -O ./modules/user/manifests/auth.pp
The first thing I did was create a new keystore.pp file, the ssh::auth package made that pretty easy:
modules/user/manifests/keystore.pp
class user::keystore {
    include ssh::auth::keymaster
}
Then I needed to do was create a keystore. The keystore is just the host you nominate to control all your client and server keys. To do that in nodes.pp I properly named my only node and stopped using the default and added a couple of new includes.
manifests/nodes.pp
node build {
    include sudo, user, ssh::auth, user::keystore
}
Run puppet and you should end up with a directory
/var/lib/keys
ready to store keys.
# puppet -v --modulepath=/etc/puppet/modules /etc/puppet/manifests/site.pp
I decided I'd update my user package by removing some files and putting the user class into the init.pp file. I had too many files in there that just didn't seem to be doing anything.
# rm modules/user/manifests/virtual.pp
# rm modules/user/manifests/unixadmins.pp
Then I added a create method in the user class in my init.pp file:
modules/users/manifests/init.pp
import "*"
class user {

    define create {
            @user { "$title":
            ensure  => "present",
            gid   => "$title",
            home    => "/home/$title",
            shell   => "/bin/bash",
            managehome => true,
            require => [Group["$title"]],
        }
        @file { "/home/$title":
            ensure => "directory",
            mode   => 700,
            owner  => "$title",
            group  => "$title",
        }
        @file { "/home/$title/.ssh":
            ensure => "directory",
            mode   => 600,
            owner  => "$title",
            group  => "$title",
        }
        @group { "$title":
            ensure  => "present",
        }

        realize User[$title]
        realize Group[$title]
        realize File["/home/$title"]
        realize File["/home/$title/.ssh"]
        ssh::auth::key{"$title":}
    }
    define client_key ($ensure = "", $filename = "") {
        ssh::auth::client{"$title": ensure=>$ensure, filename=>$filename}
    }
    define server_key ($ensure = "", $user = "") {
        ssh::auth::server{"$title": ensure=>$ensure, user=>$user}
    }
}
This code defines a new method called create, and realises all the required resources, finally it generates a new key for the user. Now we need to update our node to create ourselves a user using this new method
manifests/nodes.pp
node my-server {
    include sudo, ssh::auth, ssh::auth::keymaster, user
    user::create{"andrewmccall":}
    user::client_key{"andrewmccall":}
    user::server_key{"andrewmccall":}
}
The last step is to copy the private and public key down to a machine. It's important that you test ssh logins to this host using the new keys. Otherwise you risk locking yourself out for good! I think that's probably a good place for me to call it a night - tomorrow I'll be locking down sshd so that only users with keys can login.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Mon, 09 Aug 2010 18:37:50 -0700 Groups in puppet. http://andrewmccall.com/2010/08/groups-in-puppet http://andrewmccall.com/2010/08/groups-in-puppet Last time I ended up not being able to create my user because I didn't have a group for it and ran out of time before I needed to call it a night. So I'll start tonight by creating a group for my user. Go to the puppet config dir:
# cd /etc/puppet
Then edit the virtual file we created in our users module last time and add a group, like this:
users/manifests/virtual.pp
class user::virtual {
    @user { "andrewmccall":
        ensure  => "present",
        uid     => "1001",
        gid     => "1001",
        comment => "Andrew McCall",
        home    => "/home/andrewmccall",
        shell   => "/bin/bash",
        managehome => true,
        require => [Group["andrewmccall"]],
    }

    @group { "andrewmccall":
        ensure  => "present",
        gid     => "1001", 
    }

}
Next in the unixadmins file we need to realize our new group, it should look like this:
users/manifests/virtual.pp
class user::unixadmins inherits user::virtual {
    realize(
        Group["andrewmccall"],
        User["andrewmccall"]
    )
}
Run puppet on the local files and you'll have a new user and a group for it. It should look something like this:
# puppet -v --modulepath=/etc/puppet/modules /etc/puppet/manifests/site.pp
info: Autoloaded module sudo
info: Autoloaded module user
info: Applying configuration version '1281368198'
notice: //user::virtual/Group[andrewmccall]/ensure: created
notice: //user::virtual/User[andrewmccall]/ensure: created
Don't forget to commit the changes to the git repo.
# git add .
# git commit -a -m "Added a users module to manage users"

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Thu, 05 Aug 2010 22:04:41 -0700 Setting up users and securing my server. http://andrewmccall.com/2010/08/setting-up-users-and-securing-my-server http://andrewmccall.com/2010/08/setting-up-users-and-securing-my-server Last night I got the server upgraded to ububtu 10.04 and installed puppet. The first and only recipe we've got is one to make sure our sudoers file has the proper permissions. Tonight I'm hoping to:
  • Add myself a user
  • Automatically create me ssh key
  • Prevent root from logging in via ssh
  • Prevent users from logging in other than with a key.
  • It would be nice to be able to email me my key since I don't run puppet on my mac, though I may be convinced to go down that route if it proves too difficult.
Longer term I'm hoping to extend this same process to create user certificates for https client certificate authentication and it would be nice to use the same key, certificates and revocation process to issue new credential to users or to even lock them out. Bearing that all in mind, but not getting too hung up on stuff I'm doing later, off we go.

Create the users module

We're going to do this pretty much straight out of the puppet best practice guide, the first thing we'll do is flesh out our users module.
# cd /etc/puppet
# mkdir -p modules/user/manifests
Then create a virtual users file:
modules/user/manifests/virtual.pp
# virtual.pp
#
# People accounts of interest as virtual resources
class user::virtual {
    @user { "andrewmccall":
        ensure  => "present",
        uid     => "1001",
        gid     => "1001",
        comment => "Andrew McCall",
        home    => "/home/andrewmccall",
        shell   => "/bin/bash",
    }
}
Next let's move me from a virtual user to an actual user
modules/users/manifests/unixadmins.pp
# unixadmins.pp
#
# Realize the members of the Unix team and include any contractors

class user::unixadmins inherits user::virtual {
    # Realize our team members
    realize(
        User["andrewmccall"]
    )
}
Next we need to create an init.pp for the module.
modules/users/manifests/init.pp
import "*"
class user {
    include user::virtual, user::unixadmins
}
Now we need to go back and update the site.pp - at this stage I also add a node.pp below to manage individual hosts.
manifests/site.pp
# site.pp

import "nodes"

Exec { path => "/usr/bin:/usr/sbin/:/bin:/sbin" }
manifests/site.pp
# node.pp

node default {
  include sudo, user
}
Once I got that all setup I ran puppet from the command line:
# puppet -v --modulepath=/etc/puppet/modules /etc/puppet/manifests/site.pp
And I got an error:
info: Autoloaded module sudo
info: Autoloaded module user
info: Applying configuration version '1281041300'
err: //user::virtual/User[andrewmccall]/ensure: change from absent to present failed: Could not create user andrewmccall: Execution of '/usr/sbin/useradd -u 1001 -g 1001 -s /bin/bash -c Andrew McCall -d /home/andrewmccall andrewmccall' returned 6: useradd: group '1001' does not exist
Unfortunately I'm going to have to leave it at that for the night, see you tomorrow.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Wed, 04 Aug 2010 21:14:21 -0700 Upgrading my server and installing puppet http://andrewmccall.com/2010/08/upgrading-server-installing-puppet http://andrewmccall.com/2010/08/upgrading-server-installing-puppet I woke up this morning to a fresh install of Ubuntu 8.04 I was just itching to configure, but I had to work. So it wasn't until after the kids got fed and put to bed I could get started. What I'm aiming to accomplish tonight it to get the server configured and upgraded. The first thing I did was trim the install, I don't really want a LAMP server. I want to cut everything I don't need. The only daemon process I want is SSH at the moment so I went into aptitude and selectively removed packages I didn't want. It's worth noting here that if you're removing packages that you've no intention of installing again, make sure you do an apt-get purge or equivalent so you lose the config as well. You could probably do this with puppet and I want to automate as much of this process as I can, but I can't figure out how I can automate the upgrade, unfortunately, so I'm not going to bother with anything until I get 10.04 installed. The next step was to run the upgrade by installing the upgrade manager, and launching the process.
# apt-get install update-manager-core
# do-release-upgrade -p -m server
You'll be asked a few questions, I went for all the defaults except when asked about the grub menu. I chose to throw away the existing config and go with the package maintainer's - it's the only one that worked for me. Eventually you'll be told the upgrade is complete and asked if you want to reboot. You and I now have an Ubuntu 10.04 LTS server, next stop puppet.

Puppet

The first big question I started having about my infrastructure was how I wanted to send the config to the servers. It wasn't such a big deal with this install, since it was just the one box. There are two main ways of managing config with puppet, the first is to use the bundled puppetmaster server. There is one puppetmaster, each client machine contacts at regular intervals and asks it if there are any changes and applies the ones that it needs. Out of the box they say it's good to 20-30 machines, you can tweak a few things to get a little more out of it or run it in a more powerful web process. The second way of running it is as a more or less standalone system. You update the config however you choose on each node, then execute the puppet command to apply it. The real benefit here is you control when the config is applied. One simple way of doing that is with post-recieve or post-update hooks in git and there is an excellent article from Bitfield Consulting about doing just that. I'm leaning towards manging the Hadoop cluster I'm looking to manage with puppet after this initial install in a very similar manner. I want to either make a change and have the change pushed immediately across the cluster or control the deployment of a change - it wouldn't do for the whole cluster to suddenly go down to update some software at exactly the same time. Part of the point of using puppet on top of hudson and the other tools I'll be getting into over the coming weeks and months is to allow me to push changes across the cluster, but more importantly roll back the bad ones. Let's get the packages
# apt-get install puppet git-core
By default puppet won't be configured to start puppetd, which is fine - we'll be triggering it manually.

Chicken or the egg

We want to store all of our configuration in git, but we also need puppet to manage and ensure there is a git repository on the server that's storing the config. With git it's actually pretty easy, we can create a repo in place, commit to it, then add the actual remote repo later.
# cd /etc/puppet
# mkdir modules
# git init .
That's our repository created, the only change we want to make is we need to ignore the puppet.conf file - we'll be managing that with puppet as well. Create the file
/etc/puppet/.gitignore
puppet.conf
Basically once we've set the repository up, managing a machine with puppet should be as simple as cloning the repository and running puppet. So let's get there - Now that everything seems to be setup properly, let's create a simple puppet recipe, as is the standard, let's enforce some permissions on /etc/sudoers, just to make sure it all works. This is a bit of an extension to the standard first recipe, but we'll be extending it later.

Sudoers module

First let's create the package, this is a pretty standard layout most modules will follow.
# cd /etc/puppet/modules
# mkdir -p sudo/files sudo/manifests
Create the following files:
sudo/manifests/init.pp
import "*"
class sudo {
    include sudo::install, sudo::service
}
sudo/manifests/install.pp
class sudo::install {
  package{ "sudo": ensure => installed,}
}
sudo/manifests/sudoers.pp
class sudo::sudoers {

  file { "/tmp/sudoers":
    mode => 440,
    source => "puppet:///modules/sudo/sudoers",
    notify => Exec["check-sudoers"],
  }

  exec { "check-sudoers":
    command => "/usr/sbin/visudo -cf /tmp/sudoers && cp /tmp/sudoers /etc/sudoers",
    refreshonly => true,
  }

}

Set the rest of puppet up to call the module

Finally we need to set up puppet to call the module we've just created. We need to create a site.pp, everything else is loaded from there. In our installation we could call the file anything we like, but to keep things 'standard' we'll keep it as site.pp. Create the file
/etc/puppet/manifests/site.pp
import "sudo"

node default {
  include sudo::install
  include sudo::sudoers
}
That's it, puppet should now be up and running - test your configuration by executing the command:
# puppet -v --modulepath=/etc/puppet/modules /etc/puppet/manifests/site.pp

Finished for the day.

That's about all I can manage tonight. Tomorrow I'll continue with the puppet configuration, get it creating users and lock the server down a bit. After that I'll finally be able to start installing the software I need on the box.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Tue, 03 Aug 2010 21:00:46 -0700 Let's use puppet instead. http://andrewmccall.com/2010/08/lets-use-puppet-instead http://andrewmccall.com/2010/08/lets-use-puppet-instead So I've just trashed a perfectly good, working server install. That's right, I threw it all away, and for what you ask? For you gentle reader... and because I found a new toy that I wanted to play with, puppet. Puppet is a configuration management tool, Adobe use it to manage their hadoop cluster and it was something I knew I wanted to look at when it came time to start to manage mine. It wasn't really until I came to the process of writing down all the steps I took setting my server up, so I could reproduce the process if necessary that it occurred to me puppet was something I could should use. The previous post I'd partly written for today  was about the process of getting my server, updating it to Ubuntu 10.04 and generally getting started. Basically I was breaking the steps I took setting my server up into bite sized chunks and them writing down, from memory. For general background see yesterday's post, most of that still applies. Also reading the Atlassian Dragon Quest is useful background, the biggest difference between that and my install is probably that I'm using MySQL instead of Postgress. There isn't any real reason except I'm familiar with it and so tend to prefer it. I'll also be using hudson, not bamboo - I don't have anything against Bamboo specifically, but 10 plans wont be enough for me and I'm not willing to splash the extra cash to get more when hudson is free and in some respects better suits my needs. On top of the Atlassian stuff I'm also installing nexus, putting everything behind nginx so that it shows up neatly as a single host and locking most of the site away behind client SSL certificates. With a few holes poked through for public services. I also assume you've got a domain and that it's properly pointed at the server. I'll be using dev.andrewmccall.com throughout - which coincidentally, is mine. So, without further ado, let's get going.

The Server

I had a look around at the cost of servers, thought about hosting things at amazon, rackspace or elsewhere in the cloud but in the end settled on a hosted server at Server4You. It was recommended by a friend as fairly cheap and reliable, the server is in the EU so it's quicker for me to access than going across the atlantic. The signup process was fairly painless, I even got a phone call from a real person welcoming me and telling me my server would be online soon. After a few hours I got an email telling me it was online and ready to go. I just had to log in and select my OS. I logged in and was unsurprised to find that Server4You, like most most hosting companies, seem to only offer Ubuntu 8.10 LTS, so I installed the Ubuntu 8.04 LTS - LAMP - 64bit image. The same image I'm in the process of overwriting my fully setup server with right now. It can take up to 2 hours, so I'm going to call it a night at that and I'll carry on tomorrow.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Mon, 02 Aug 2010 21:27:23 -0700 New development server http://andrewmccall.com/2010/08/new-development-server http://andrewmccall.com/2010/08/new-development-server Things around here have stalled a bit I've not had much free time what with a new job and travelling. The time I have had I've spent getting a build server setup. Replacing my ageing trac/subversion install is something I've meant to do for a while and just never got around to. Ultimately I'm working on a continuous deployment solution for Sproozi, but while I do that I'm also keen to get my other public and private projects into a CI build cycle and get my maven artifacts deployed so they're useful. The other major goal was to move all my main projects out of trac/svn and into JIRA/Confluence/Fisheye/Git. Trac and subversion are fine tools, and they've worked well for me for many years, but trac suffers when it's running more than one project; you either need to work around the tool or have separate installs per project and I can get JIRA, Fisheye and Confluence for $10 each which is a great deal. I have no real complaints about svn, except I've started using git as my preferred client and I'm sick of typing 'git svn command' whenever I want to do anything. Also my subversion repository holds a fair bit of code from a few projects both new, old and dormant as it grows checking out gets irritating. I'm happy with the move to GitHub and public hosting of my other projects, I like git and I liked the idea of promoting projects into repositories of their own and git lets me take the history with the project. So I've decided I'll keep my subversion repository, use it as I do now as a sandbox to keep code I'm working on in, for code I don't think is quite ready to be promoted into a project of it's own. When a project is ready I'll move it (and all of it's history) out of subversion and into a git repository of it's own. My public projects are all in GitHub and I don't see any point in using my local tools to manage them in anyway. So I'll keep them all over there. Any new ones will get promoted over there too. Over the course of the next few days/weeks I'll document what I did here, partly in case anyone else cares, partly so I can do it again if I ever need to. I'm not sure how many posts it will take me because I'm not quite finished the process yet.
Media_httpimgzemantac_fujbt

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Wed, 02 Jun 2010 20:24:23 -0700 Getting along with Eclipse http://andrewmccall.com/2010/06/getting-along-with-eclipse http://andrewmccall.com/2010/06/getting-along-with-eclipse It's been a week or so with a few good days coding in Eclipse, I even took IDEA off my own machines and replaced it so that I'm only working in the one environment and it's going well. I'm pretty much using the default settings and only adding to them a little as I go. I'm resisting the urge to change the key bindings to the IDEA ones. So far I've found a few things Eclipse does that I really like, it has some good highlighting features that make it easy to see where classes, variables, parameters etc are being used. Some IDEA does better - I miss the key bindings for generating code, a lot and it's about the only thing I've carried over and added myself. One thing that really bothers me about Eclipse and that I'm going to see if I can spend some time sorting out tomorrow is the order of maven imports. They're in classpath order, which I suppose in some circumstances is good, but for browsing or trying to look at the imports it's frustrating. 9 times out of 10 I'm looking to see if something is there or looking into the dependencies themselves for something and trying to dig through that mess takes longer than it should. In fact I have to say the whole 'project explorer' in Eclipse is a bit lacklustre. IDEA's is simpler without losing any of the functionality. I'm probably missing something and just need to find some options to make it work more like I'd like (or use a completely different view). Eclipse has a lot of preferences I've never looked at. Aside from that it's all good. I'd have to say some bits of IDEA are more polished, but in other ways I prefer Eclipse. The choice to drop IDEA completely though because I need to use Eclipse at work was a good one - I don't think I'd be making the same progress if I was switching between the two yearning for IDEA all day at work.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Sat, 22 May 2010 21:08:09 -0700 So long IDEA http://andrewmccall.com/2010/05/so-long-idea http://andrewmccall.com/2010/05/so-long-idea I've been using Intellij IDEA for years, I pretty much swear by it for development and I have no real complaints. But now I've got a new job and they use Eclipse. Now, so do I. I figure there is no way to properly learn to use Eclipse if my heart is still in IDEA, so there's nothing for it except to say goodbye IDEA and move over to Eclipse for everything. Looking around the Eclipse ecosystem and there are an awful lot of what look to be excellent plugins. I know IDEA had a plugin system but the ecosystem never seemed as good and I never really got into them. Now it's off to import my projects and see what's what. I did try this a few weeks ago after my interview, but gave up with the excuse that I wanted to get some work done.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall
Thu, 20 May 2010 08:27:10 -0700 OAuth 2.0 http://andrewmccall.com/2010/05/oauth-2-0 http://andrewmccall.com/2010/05/oauth-2-0 I've been updating my OAuth library to support OAuth 2.0 mostly so I can add Facebook to Announce.ly and Sproozi, but more on that later. OAuth 2.0 is similar to 1.0 but changes a few key things fundamentally and isn't backwards compatible. What's wrong with 1.0, doesn't it work? It does, but probably the biggest issue is the fact that you have to sign the message knowing all it's content beforehand. This works well if the data is on the querystring in a GET request or for simple operations but isn't optimal if your data is part of the POST body. It also means you have to construct your requests in a certain way, which is a bad thing. Take photo, audio or video data - to post that you'll need to sign the whole request and it's not clear how it should work with multipart data. There are several extensions to the spec that deal with some of these issues, but the fact that there are non standard extensions to do something pretty standard kinda says it all. Even if you're not dealing with these issues you still have to work with your requests as units where you know the whole content beforehand. What's new in OAuth 2? OAuth 2.0 in it's simplest form works over HTTPS connections and simply asks for a token - the security and trust are built in to the protocol. It's that easy. OAuth 2.0 sill lets users sign messages to transmit them over insecure channels, plain HTTP, but the signing methods are much easier to implement. Gone is the complicated parameter normalisation algorithm and in it's place is a much simpler version that doesn't require POST data in the signature. So even with multipart submissions it should just work. At the moment I'm cleaning things up and preparing the oauth library to work with oauth 2.0 and changing the way it works to reflect the simpler way oauth 2.0 does. You can check it out on GitHub [http://github.com/andrewmccall/oauth]

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/760452/DSC_0002-2.jpg http://posterous.com/users/4SIUJafSDfHP Andrew McCall andrewmccall Andrew McCall