Blog

Scott Forsyth’s Blog – Windows Server 2008 R2 DNS Issues

I use a service at home to unlock region-locked web content, particularly internet video. As Iā€™ve mentioned previously, I run a Windows 2008 R2 server on our home network which is our domain controller, and (as a result) our DNS server too.

The service I use for unlocking content requires that you set the DNS server on the network to the values it specifies. Thatā€™s not viable for me because of course the client machines need to use the internal DNS server in order to be able to find the domain controller, but no problem – the windows server VM can act as the DNS server just fine, handle requests relating to the internal network domain itself, and forward everything else off using the forwarders I specify (which come right from my content unlocking service).

This worked great until a few weeks ago, and then it suddenly stopped working.

I donā€™t know why and Iā€™m not quite technical enough to fully grasp the details, but the problem was EDNS (whatever that is). The blog post Iā€™ve linked above talks about it more depth, but the bottom line for me is that once I turned EDNS off everything worked fine.

Scott Forsyth’s Blog – Windows Server 2008 R2 DNS Issues

Blog

[youtube https://www.youtube.com/watch?v=UBr3MM9_zd4?feature=oembed&enablejsapi=1&origin=http://safe.txmblr.com&wmode=opaque&w=500&h=375]

Itā€™s been a while since Iā€™ve shared one of my somewhat-humorous Friday updates, so I present for your viewing pleasureĀ ā€œSh*t Project Managerā€™s Sayā€

Weā€™ve certainly watched this a few times on my team at work and subtle references to it slip in all over the place. I donā€™t think Iā€™ve previously shared it here though, so enjoy!

Blog

5 Keys to Effective Project Meetings

I read the article (linked above) by Brad Egeland a couple of weeks ago, and I wanted to share it here because I agree with him, and I think these are great tips. They also apply to any meeting, not just project meetings.

The article also serves as a great reminder that project management is all about people. You could be the best in the world overseeing requirement elicitation for a project, turning that into a work breakdown structure, then a network diagram, then a project plan with schedule and cost baselines… if you canā€™t run an effective meeting then youā€™re unlikely to be able to successfully execute upon your plan. These are skills that cannot be forgotten about and the importance of which should not be minimized.

Here are five key practices you can follow to ensure your meetings are effective, well attended and convey the proper information while staying on track and on time.

Sometimes the operative word in your job title isĀ ā€œproject,ā€ but more frequently itā€™sĀ ā€œmanager.ā€

My favourite piece of advice from Brad is the first one: Send out an advance agenda. Adding an agenda to every meeting I host has changed my life. The mere act of forcing myself to think carefully about the agenda ahead of time has inherent value for me, and youā€™d be surprised (or maybe you wouldnā€™t) how often giving this the right thought causes me to reevaluate in some way, maybe by adding or removing invitees, maybe by lengthening or shortening my planned meeting length, or maybe by changing the communication medium altogether and replacing the meeting with a phone call or an email. It also helps participants identify whether they really should be involved or not: maybe Iā€™ve misunderstood someoneā€™s role and they wonā€™t have anything to contribute, or maybe thereā€™s someone on their team that the meeting should be forwarded to for the benefit of obtaining whatever additional insight that person holds. It really helps make meetings effective and minimize the need for follow-ups.

To my mind, in fact, itā€™s so important that I would go a step further ā€“ or more accurately, take one additional step back: define a one-sentence meeting ā€œpurposeā€ up front as well, and share that in the invite too. It doesnā€™t have to be complicated by any means, but itā€™s a powerful tool to use if (when) a particular meeting starts to get off track, and itā€™s also something concrete to come back to at the end. Have we collectively achieved the defined purpose? If not, are we each clear on our individual next steps in order to move expeditiously toward that goal?

You can think of a meeting like a small project in its own right, if it helps: the meeting purpose statement is your project objective, and the agenda is the scope statement that flows from that. You could even include anĀ ā€œout of scopeā€ section if you feel in advance thereā€™s a risk of people getting off topic for one reason or another.

5 Keys to Effective Project Meetings

Blog

Windows Authentication on External Websites

My home network is domain-based, and Iā€™m running a Windows Server 2008 VM as the domain controller. Iā€™ve written
in the past
about how to use PHP to do authentication using domain
credentials, and that works great for some scenarios. As a case in point, I use
Pydio to host a web-based file manager that
allows me access to my files when Iā€™m out and about. Pydio runs on a linux
server VM on my home
server
, and it actually includes a built-in mechanism to authenticate
against an LDAP server (the Windows domain controller) so I didnā€™t have to
modify it with my PHP code. The principle is the same, though.

image

This is all good stuff for anything hosted on my home
server, but what if that isnā€™t what I want? What if I want to host something on
my external, public webserver, and still use my active directory credentials to sign in to
it? And, while weā€™re at it, what if I want to be even more restrictive and
limit access to a particular organizational unit within active directory?

As luck would have it, these are all problems that I solved
this week. Read on!

Creating a Reverse SSH Tunnel

The first thing we need is to establish a secure connection
between the external webserver (the VPS) and the internal webserver (the local
linux VM). Weā€™re going to use a reverse SSH tunnel to do this,
and, specifically, weā€™re going to use a tool called autossh that will keep an eye on
the tunnel and restart it if something goes wrong.

Iā€™ll skip most of the technical detail here, but essentially
a reverse tunnel is going to forward a particular port on the external server
to a particular port on the internal server. Itā€™s called a reverse tunnel
because itā€™s the internal server that triggers the connection. Thatā€™s important:
the internal server can reach the external one just fine, but not the other way
around (thanks to things like me having a dynamic IP address for my home
internet connection, my home routerā€™s firewall, DHCP, etc).

I installed autossh on my Ubuntu server VM:

sudo apt-get install autossh

And then wrote a one-line script that I placed in /etc/network/if-up.d:

#!/bin/sh
su -c "autossh -M 29001 -f -N -R 8080:localhost:80 remote-server.com" localadmin

Teasing this apart just a little, it uses the local account ā€œlocaladminā€
to run the command enclosed in the quotation marks. That command forwards port
8080 on ā€œremote-server.comā€ to port 80 on the local machine.

For this to work itā€™s essential that the user ā€œlocaladminā€
is able to log on to ā€œremove-server.comā€ without
needing to enter a password
.

The Local Server

The local webserver is where most of the heavy-lifting is
going to take place. The first thing I did was create a new virtual host in the
webserver configuration on that machine. Iā€™m using lighttpd, so my configuration looks like
this:

$HTTP["host"] =~ "^auth.gateway" {
    $HTTP["remoteip"] !~ "127.0.0.1" {
        url.access-deny = ("")
    }

    server.document-root = "/home/jason/WebServer/Production/auth.gateway"

    url.rewrite-once = (
        "^(.*)$" =>"auth.php"
    )
}

Essentially it creates a new host with the hostname ā€œauth.gatewayā€
thatā€™s only accessible to the local machine (127.0.0.1). Any request that comes
in regardless of the URI is rewritten to a file called auth.php in the document
root.

The hostname here isnā€™t real (i.e. thereā€™s no public DNS
entry for it), and thatā€™s probably a good thing for the sake of locking down
security as tightly as possible. Also on that line of thinking is the fact that
access is limited to the local machine. The webserver doesnā€™t know that requests
coming through our SSH tunnel are coming from another machine thanks to the
virtues of port forwarding ā€“ it thinks theyā€™re coming from other processes
running locally (i.e. coming from 127.0.0.1).

Next is auth.php itself, the engine that runs all this
stuff:

<?php
    session_name ('AGSESSID');
    session_set_cookie_params(600);
    session_start();

    $domain = "testdomain.local";
    $domaincontroller = "dc1.testdomain.local";
    $requiredou = "FamilyMembers";
    $authkey = "big-random-string";

    if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['HTTP_X_AUTH_KEY']) || $_SERVER['HTTP_X_AUTH_KEY'] != 'big-random-string') {
        header('WWW-Authenticate: Basic realm="Authentication Required"');
        header('HTTP/1.0 401 Unauthorized');
        exit;
    } elseif (!isset($_SESSION['AuthKey']) || $_SESSION['AuthKey'] != md5($_SERVER['HTTP_X_FORWARDED_FOR'].$_SERVER['PHP_AUTH_USER'].$_SERVER['PHP_AUTH_PW'])) {
        $ldap = ldap_connect($domaincontroller);

        ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
        ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

        if (!$bind = ldap_bind($ldap, $_SERVER['PHP_AUTH_USER']."@".$domain, $_SERVER['PHP_AUTH_PW'])) {
            header('WWW-Authenticate: Basic realm="Authentication Required"');
            header('HTTP/1.0 401 Unauthorized');
            exit;
        } else {
            $result = ldap_search($ldap, "DC=".implode(",DC=", explode(".", $domain)), Ā "(samaccountname=".$_SERVER['PHP_AUTH_USER'].")");
            $entries = ldap_get_entries($ldap, $result);
 
            if (strpos($entries[0]['distinguishedname'][0], "OU=".$requiredou) === FALSE) {
                header('WWW-Authenticate: Basic realm="Authentication Required"');
                header('HTTP/1.0 401 Unauthorized');
                exit;
            } else {
                $_SESSION['AuthKey'] = md5($_SERVER['HTTP_X_FORWARDED_FOR'].$_SERVER['PHP_AUTH_USER'].$_SERVER['PHP_AUTH_PW']);
            }
        }
    }
?>

As you can see, this is quite a bit more sophisticated than
the previous example in my SSO post, but letā€™s tease this one apart at a high
level too.

When the script is loaded, it first checks to see if the thereā€™s
a username, password and ā€œAUTH_KEYā€ contained within the HTTP headers of the
request. If so, it verifies that the ā€œAUTH_KEYā€ is what it was expecting, and it
tries to use the username and password to establish an LDAP connection to the
Windows server VM. If thatā€™s successful, it retrieves some information about
the user and checks if theyā€™re a member of the required organizational unit.

If all that works it sends back an empty page, but,
crucially a HTTP 200 status (meaning everything is OK). If any of those checks fail
then it sends back a HTTP 401 status (unauthorized) header instead.

In addition to this, the script creates a PHP session with a
custom name. The name is custom to avoid collisions with any session that
the external server may be creating, but essentially the session lasts 10
minutes, and if subsequent requests come in for a user thatā€™s already been
authorized then it skips all the checks and just sends back the HTTP 200
header. It does that because without it, every HTTP request made to the remote
server (not just every page served, but every image on every page, every CSS
file, JavaScript file, etc, etc) would involve a query to the domain controller
to validate the credentials, and thatā€™s a potential bottleneck with performance
implications.

The Remote Server

My remote server is running nginx as its webserver (Iā€™m new to it,
but I think I like it better than lighttpd. Thatā€™s kind of beside the point
though). The configuration looks like this:

server {
    server_name example.com;
    listen 80;

    root /home/jason/example.com/www;

    auth_request /__auth;
    auth_request_set $saved_set_cookie $upstream_http_set_cookie;
    add_header Set-Cookie $saved_set_cookie;

    location = /__auth {
        auth_request off;

        proxy_pass http://localhost:8080;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header Host auth.gateway;
        proxy_set_header X-Original-URI $request-uri;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Auth-Key "big-random-string";
    }
}

When we tease this one apart, there are two key details. One
is that ā€œauth_requestā€ declaration in the fourth line. As per nginxā€™s
documentation
, auth request ā€œimplements client authorization based on the
result of a subrequest.ā€ In other words, instead of nginx doing the
authentication itself it forwards the request on. The configuration above
defers the authentication of http://example.com to http://example.com/__auth.

The second crucial chunk of the configuration file is
everything within the ā€œlocation = /__authā€ declaration. The first thing this does
is turn off the ā€œauth_requestā€ functionality (otherwise, weā€™re stuck in an
endless loop), and it then creates a proxy to redirect any requests to
http://example.com/__auth to http://localhost:8080. Port 8080, if you recall,
is in turn forwarded through our SSH tunnel to port 80 on the local server.

Additionally, it sets the hostname involved in the request
to ā€œauth.gateway,ā€ forwards a couple of other pieces of information as headers,
and, for some added security, sends an ā€œX-Auth-Keyā€ header that our PHP script
checks for.

Back outside of this block the ā€œauth_request_setā€
declaration takes the session cookie from our PHP script and saves it to a
variable, then the following line (ā€œadd_headerā€) sends that cookie back to the
clientā€™s browser as part of the response they receive.

Done!

Real World Problems with All This

I mentioned earlier that we set a session cookie as part of
the whole interaction to avoid the need to query the LDAP server for every HTTP
request the remote server receives, and I said this was to avoid a performance
bottleneck. Thatā€™s true, but we still have a performance bottleneck here: for
every HTTP request the remote server receives itā€™s still querying the local
server through our SSH tunnel, even if all the local server is doing is
responding that the credentials are good based on the existence of the session
cookie.

This communication has to take place over my home internet
connection, which is absolutely not what my ISP intended it to be used for. I don’t think it’s against their terms and conditions or anything like that, itā€™s just that it isnā€™t
really fast enough.

If the site deployed on the remote server was one of my own
making then Iā€™d modify this approach to create an authentication API of sorts
on the local server, and Iā€™d do the session setting and credential caching
entirely on the remote server, drastically reducing the number of queries to
the local server (all the way down to a single query, in fact, when the session
is first created and the user logs on).

The other problem is one of securing the whole interaction.
Weā€™re using ā€œbasicā€ HTTP authentication methods here, which means that the
username and password are passed around in the clear (theyā€™re not encrypted or hashed as
part of the process). Thatā€™s necessary: the auth.php script has to receive the
password in cleartext because it has to pass it to the Windows server to check
its validity. Itā€™s also not an issue with the communication between the remote
and local webservers, because that happens through an SSH tunnel thatā€™s using
public/private keypairs to provide encryption. It is a problem for the
communication between the user and the remote webserver though, and it leaves
our user vulnerable in several ways (especially if theyā€™re using a public WiFI
hotspot). Essentially what Iā€™m getting it is that you must use SSL between the user and the remote server.

Conclusion

This is not the most optimal way of doing things,
particularly in regards to the bottleneck it creates by deferring authentication
of every HTTP request to my local server which is connected to the internet
using a typical consumer-grade ADSL connection, but as a quick and dirty way of
securing resources on my public webserver without needing to modify the
resource itself in any way, it works great!

Enjoy!

Blog

Compiling Third-Party Modules Into Nginx

I want my public web server, which runs nginx, to authenticate against my active directory server using LDAP. Iā€™ve written in the past about how to use PHP to authenticate against active directory in this way, but there are a couple of problems: my active directory server isnā€™t accessible to the internet, and I want to use standard HTTP authentication instead of username and password boxes included on a webpage.

The answer, I think, is to put an authentication PHP script on my home server, make that available to the public web server through an SSH tunnel, and then use nginxā€™s Auth Request module to authenticate against it using the public server as a proxy.

This is – I hope – less complicated than it sounds. Weā€™ll see, and Iā€™ll post more if and when Iā€™m successful, but the problem Iā€™ve initially run into is that nginx in Ubuntuā€™s repositories doesnā€™t include the Auth Request module. I have remove nginx and re-install it from source, compiling it with the additional module included.

Itā€™s a bit of a daunting process, but the page Iā€™ve linked seems like it will take me through it step by step.

Wish me luck!

Compiling Third-Party Modules Into Nginx

Blog

The Trials and Tribulations of my Connected World

Iā€™ve written many times on this blog about ROWE (the results only work
environment). Itā€™s the structure under which I work, and Iā€™m a big fan. One of
the key tenets of ROWE is that itā€™s available to everyone: itā€™s not something
reserved for those at a certain paygrade, itā€™s not restricted to leaders, itā€™s
not something you have to apply to be a part of, or provide some kind of
justification of your particular circumstances to gain entry. There should be
no barrier to entry.

When I first
wrote about ROWE on this blog
, I lamented that at my organization there is
a barrier to entry, to a certain extent. Not by design, but simply because our
communication mechanisms are restricted by our firewall and access to them from
outside the corporate network is barred. The barrier to entry, as I see it, is
having a company-issued cellphone. If you have one you can be available from
wherever you might happen to find yourself, and if you donā€™t youā€™re tied to
your computer.

I didnā€™t have a company-issued cellphone when I wrote that,
but I do now. There it is above. Itā€™s the one with the darker wood effect
amongst my bamboo effect personal devices.

I love it, and I hate it. I donā€™t want it, and I wouldnā€™t
give it back. Read on to learn why!

Why I Love It, and How it Supports ROWE

Quite simply, when I thought not having this device
constituted a partial barrier to ROWE entry, I was right. Last week Flo and I
went to Winnipeg and I worked from there for the week. I spent most mornings
sitting in Floā€™s sisterā€™s kitchen working at my laptop, then weā€™d typically go
for lunch together and Iā€™d spend the afternoons with my extended family. I was
available throughout to respond to emails and IMs. If somebody called my office
phone number then their call was seamlessly forwarded to the phone in my
pocket. Most of the work people I interacted with would have had no idea I wasnā€™t
at my desk, let alone that I wasnā€™t even in the same time zone. That wouldnā€™t
have been possible if I didnā€™t have this phone.

Why I Hate It, and How it Contradicts ROWE

The point ROWE is that Iā€™m an adult, and I work how, when
and where I choose to. I could be
working at any time and from any place. Having the phone feels a little bit
like I am working at all times, from all
places. Essentially having the phone means the thing I find most challenging about
working in a ROWE ā€“ knowing when to switch off ā€“ is magnified exponentially.
Obviously the phone has an ā€œoffā€ button and, being an adult and all, I am free
to use it as I choose, but I simply donā€™t find it as easy as that. Take last
week as an example: when I was out spending my afternoons with family every now
and then Iā€™d receive a work-related message of some description. I probably
dealt with 80% of them right away, because 80% of my job is more about getting
the right people in contact with one another than it is about actually doing
something myself. The remaining 20% I flagged to deal with the following morning.
The inward flow of these messages is not overwhelming, but it is constant. If I
disconnect entirely, even for an afternoon, the sheer volume of stuff that
builds up is overwhelming. I donā€™t
like to feel overwhelmed, so I keep my phone on because itā€™s easier to take a
couple of minutes out of what Iā€™m doing a few dozen times than it is to try to
deal with a few dozen things at once when I eventually choose to reconnect.

There are certainly times where I hate remaining available
and connected and doing so gets in the way of other things Iā€™m doing at that
moment, but despite that the logic above kicks in and even when I need a break
I end up being reluctant to take one. And, as I mentioned, the inward flow of
messages really is constant. With most of the people I work with also being in
a ROWE it starts at about 6am and continues until about 1am, each one bringing
with it a little ā€œdingā€ noise. I feel like Pavlovā€™s dog sometimes.

Why I Donā€™t Want It

Despite the occasional strength of my negative feeling
toward my phone, none of that has anything to do with why I donā€™t want it. The
benefits outweigh the drawbacks, and the issues I have with it are a function
of my choices, not of the technology. I can get better with it, and over time I
will.

The reason I donā€™t want it is that I have a perfectly good
phone already. You may have noticed it in the photo up top: itā€™s the bamboo
effect one in the middle. Why do I need to carry two phones with me? Thereā€™s no
technical barrier to my company turning on the ability to support a ā€œbring your
own deviceā€ policy, and in fact the technology required is already in place. Itā€™s
disabled, because the policy is that the IT department wonā€™t allow you to get
email on your phone unless they have the ability to remotely wipe the whole
thing. Not just securely erase company data, but securely erase everything. I
assume this is a case of policy failing to keep up with emerging business trends.
Iā€™d think they must realise that weā€™re going to have to BYOD policy someday, so
I get hung up trying to understand why they wonā€™t just get it done right away.
Iā€™ll continue to advocate for a BYOD policy in my workplace, exceptā€¦

Why I Wouldnā€™t Give it Back

My inability to switch off was a minor problem when I
carried a laptop. When that laptop was supplemented with a phone it became a
bigger problem. If that work-only device were replaced with an app on my
personal device through which I access work stuff? It could be disastrous. I
never switch my work phone off, but I do leave it at home when we go out
somewhere in the evening or on weekends. I take my personal phone with me
everywhere though. I assume that BYOD technology includes functionality that
would let me turn ā€œworkā€ off while keeping ā€œpersonalā€ switched on, but am I
disciplined enough to use that function? Probably not.

Blog

Raspberry Pi Whole Home Audio: Playing Music

Itā€™s very rare that I tweet teasers to my blog post, but
last weekend I was so excited to be making progress on my Raspberry Pi Whole
Home Audio
project that I told the world Iā€™d be publishing this one on
Thursday.

Here we are on Friday morning. Thereā€™s doubtless a lesson in
here for me about making promises I canā€™t keep, but Iā€™m hoping youā€™ll forgive
me when you read about what Iā€™ve done.

If youā€™ve been following my #RPiWHA Project
hashtag on this blog then youā€™ll know that when we left off last time I had
three Raspberry Pis networked together with synchronized clocks, and one of
them had access to the internet and the music library I keep on my home server.
Thatā€™s important, but not especially exciting. Today weā€™re going to move in a
more exciting direction, though.

Today weā€™re going to put Pis #2 and #3 aside, but weā€™re
going to get Pi #1 playing music!

Specifying and Testing the Piā€™s Audio Output

The Raspberry Pi has two options for audio output. It has a
3.5mm analog output, and digital output through its HDMI port. It decides which
output to use automatically ā€“ if you have a HDMI monitor plugged in then the Pi
will detect this and assume you want to use HDMI for audio too.

Thatā€™s not the situation for me (my Pi is ā€œheadlessā€ and
doesnā€™t have a display connected at all), and audio comes out of the 3.5mm
output automatically ā€“ which is what I want. If you need to specify, you can
run:

sudo amixer cset numid=3 1

The digit 1 at the
end means the Pi should use the analog audio output. Putting 0 there instead would mean auto-detect
(the default) and putting 2 would
mean digital output over HDMI.

Plug in some headphones or speakers and run:

aplay /usr/share/sounds/alsa/Front_Center.wav

You should hear a voice saying ā€œfront centre.ā€

Install Mopidy

Weā€™re going to install music playing software called mopidy.
It provides a web-based interface so you can control your music, or there are
controller apps available in your app-marketplace of choice. Mopidyā€™s website
takes you through the
install process in detail
, but Iā€™m going to summarize the commands here:

wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add -
sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/mopidy.list
sudo apt-get update
sudo apt-get install mopidy python-setuptools

Done! We now have a basic install of mopidy, and the especially
astute amongst you will have noticed that weā€™ve also installed a package called
python-setuptools. Mopidy is written
in the python programming language, and the latter package is going to help us
with installing and setting up some mopidy extensions in an automated way. The
first thing weā€™re going to do is install something called pip, which is a tool for installing python packages:

sudo easy_install pip

Now that we have that, weā€™re going to in turn use pip to
install some mopidy extensions:

sudo pip install Mopidy-MusicBox-Webclient
sudo pip install Mopidy-WebSettings

With those commands weā€™ve added a web-based interface to our
player so we can control it from a browser on another computer or mobile
device.

Setting Up Mopidy

Weā€™re almost ready to start mopidy and try things out, but
there is a little bit of initial setup to be done first. Edit the file ~/.config/mopidy/mopidy.conf. In the http section, change the following line
so that the web interface becomes accessible to any device on your network:

hostname = ::

In the local
section, tell mopidy where it should find your music library. In my case:

media_dir = /mnt/music

Save the file and exit. The next step is to tell mopidy to
scan your music folder:

mopidy local scan

If, like me, you have a large music collection stored on a
network share, be prepared for this to take a very long time. I started it
running before I went to bed, and it eventually completed the process about 45
minutes after I got up the following morning.

When itā€™s done though, weā€™re ready! Run mopidy:

mopidy

Itā€™ll take a little while to fully start up, but when you
see the line

INFO     HTTP server running at [::]:6680

that means weā€™re good to go. Open the browser on your
computer or mobile device and point it to
http://192.168.1.71:6680/musicbox_webclient (replace 192.168.1.71 with the IP
address of your Pi as appropriate). Go to Browse, Local Media, and select a
song!

If all is well the music will be playing through the
headphones or speakers attached to the Pi, and weā€™re all done until the next
installment ā€“ rerouting the audio from Pi #1 and streaming it, synchronized, to
Pis #2 and #3 instead.

Enjoy!

Blog

Permission to Lead

At the office I so rarely visit I have a quote that Iā€™ve
printed and pinned to the wall. It comes from Rear Admiral Grace Hopper, who was a
U.S. Naval officer and an early computer programmer (she developed the first
compiler for turning source code into object code).

In a couple of my recent
posts
Iā€™ve made mention of a cultural evolution thatā€™s underway in my workplace. Itā€™s
not a revolution ā€“ itā€™s us collectively choosing to be much more deliberate
about using the values we already hold to better deliver benefit to our
customers. As a part of that weā€™ve defined ten core values, or mantras, or
whatever you want to call them. I donā€™t know whether or not my employer would
want me to reveal them in a public forum like this. Probably not yet, at least,
given that the evolution is in its infancy: weā€™re still in the process of socialising
them internally and defining what they mean to each of us individually, to our
workgroups and teams, and so on. In lieu of the ones from my organization, hereā€™s
an example of a similar-in-spirit core value from
another company
(Zappos.com):

  • Do more with less

Today one of my colleagues and I were talking about our ten
and poking some gentle fun at them. We were coming up with a handful of jokey
possible additions:

  • Try turning it off and back on
  • ā€œThatā€™s what she saidā€

Anyway, I said that ā€œitā€™s easier to ask forgiveness than it
is to get permissionā€ should be added to our list. I was joking. But should I
have been?

I like Grace Hopperā€™s quote so much because, on the face of
it, itā€™s about rebelliousness and lack of respect for authority. Thatā€™s
typically someoneā€™s immediate takeaway when they first read it, and those are
qualities I like to pretend I have. Except I donā€™t, really ā€“ I pretty much do
what Iā€™m told.

Itā€™s been a good while since I printed that and first pinned
it to the wall of my cube, though. Iā€™ve gained some seniority in that time, and
as I was thinking about this today it occurred to me that nobody really tells
me what to do anymore. My leaders set direction, provide clarity around whatā€™s
important (and why) where necessary, provide guidance where I need it, and then
they trust me to do whatever it is that I do.

Dig just very slightly beyond the surface of Graceā€™s quote,
and this is, Iā€™m sure, exactly what she was talking about. Grace was, after
all, a senior military officer: I highly doubt she was advocating for a lack of
respect for authority. What sheā€™s talking about is ownership, and
accountability. Sheā€™s saying that if you donā€™t have the necessary autonomy to
demonstrate those qualities then thatā€™s a problem so serious that you should be
taking immediate action. If thereā€™s red tape or dumb business rules that are a
barrier to doing what you know to be the right thing then you absolutely need
to be finding a way through it, and sooner rather than later. I think thatā€™s
something worthy of inclusion in any organizationā€™s core values.

Thinking about all this also got me thinking back to how the
quote became words that I choose to live by in the first place. A couple of years
ago I worked at my companyā€™s call centre, on a team responsible for operations
and process improvement initiatives. I used to provide coaching to a handful of
junior teammates. From time to time we would identify an opportunity for
improvement in one of the ancillary, supporting business processes, but being a
process on the edge of the core business weā€™d sometimes struggle to find
someone from the key leadership to identify as owning the process and provide
sponsorship for improvement. Iā€™d always provide the same wisdom: ā€œIf thereā€™s
one thing Iā€™ve noticed about where we work,ā€ Iā€™d say, ā€œitā€™s that if you act
like youā€™re in charge of something then youā€™ll very quickly find that you are.ā€

I think at the time I thought I was joking about that too,
and that little running joke is what led me to first put Graceā€™s quote up on
the wall. Even if I did think it was a bit of a joke though I did endeavour to embody
those words, and with the benefit of reflection it now seems as though Iā€™ve advanced
my career since then in part off the back of simply acting like Iā€™m in charge
of stuff. Interesting.

Really though, this shouldnā€™t be surprising. My vocabulary
has become more sophisticated in that time too: I now see more clearly that ā€œacting
like Iā€™m in charge of stuffā€ is just a slightly tongue-in-cheek synonym for our
theme of ownership and accountability.

Once upon a time I used to wonder to myself why merely
acting like I was in charge of stuff so often proved to be such a powerful tool
in my toolbox. When you frame it in those more sophisticated terms the answer
is clear. The reason it worked so well at my workplace is because we have a
culture that recognizes, values and rewards leadership attributes like these no matter the level of the employee they come from.
The question I should have been asking is why wasnā€™t it like that at previous
companies Iā€™ve worked for?

Thankfully, the answer to that one doesnā€™t matter to me
anymore.