Advent of Code 2018

Let’s do it again! I’m starting a day late, but much better than last year 😄!

This time around, I’m hoping to solve each problem in both Python and Racket, both to show an example of how the languages differ and … well, because I can 😇.

EDIT 2018-12-05: Yeah… I’m not actually going to do these in both Racket and Python. The solutions are ending up being near direct translations. Since there are probably fewer people solving these in Racket, I’ll do that first and Python eventually™.

As always, these problems are wonderful to try to solve yourself. If you agree, stop reading now. This post isn’t going anywhere.

If you’d like to see the full form of any particular solution, you can do so on GitHub (including previous years and possibly some I haven’t written up yet): jpverkamp/advent-of-code


Simple LocalStorage Notepad

I have a large number of keyword bookmarks in whichever browser I happen to be using at the time that I’ve been building up over the years1. One of the ones I particular enjoy is text: data:text/html, <html contenteditable>. What that does is open a new tab where I can take notes, completely locally. It’s really handy… but there’s one big problem: I often accidentally close the tab and lose whatever I had been typing. So I decided to take a few minutes to write up a simple extension of the idea that would save the data to LocalStorage.


Adding HSTS to Redirects in Apache

TLDR:

# Use 'always' so headers are also set for non-2XX and unset to avoid duplicates
<IfModule headers_module>
	header unset Strict-Transport-Security
	header always set Strict-Transport-Security "max-age=16070400; includeSubDomains;"
</IfModule>

Slightly1 longer version:

HTTPS everywhere is a worthwhile goal. Even when you have traffic that isn’t super interesting or sensitive by itself, the fact that you’re encrypting it makes traffic that really does need to be encrypted safer against tools that grab all of the encrypted traffic they can to decrypt later if/when possible.

One of the downsides of using HTTPS though is that without certain things in place, many users will still type domain.com in their address bar from time to time, completely missing out on the https://. While you can immediately redirect them, that very first request is a risk, since if a man-in-the-middle attack happens to catch that request, they can downgrade the entire connection.

Enter HTTP Strict Transport Security (HSTS). It’s a HTTP header that you can send on the first HTTPS connection you establish with a compatible client. Once you’ve done that, any further requests (until the header’s TTL expires without being renewed) will be sent to https:// no matter what the user types. Which solves the first request problem for all sessions… but it still doesn’t fix the very first time you have to get the header. So how do you fix that?


Counting and Sizing S3 Buckets

A long time ago in a galaxy far far away, I wrote up a script that I used to take an AWS S3 bucket and count how many objects there were in the bucket and calculate its total size. While you could get some of this information from billing reports, there just wasn’t a good way to get it other than that at the time. The only way you could do it was to… iterate through the entire bucket, summing as you go. If you have buckets with millions (or more) objects, this could take a while.

Basically:

conn = boto.connect_s3()
for bucket in sorted(conn.get_all_buckets()):
    try:
        total_count = 0
        total_size = 0
        start = datetime.datetime.now()

        for key in bucket.list_versions():
            # Skip deleted files
            if isinstance(key, boto.s3.deletemarker.DeleteMarker):
                continue

            size = key.size
            total_count += 1
            total_size += size

        print('-- {count} files, {size}, {time} to calculate'.format(
            count = total_count,
            size = humanize.naturalsize(total_size),
            time = humanize.naturaltime(datetime.datetime.now() - start).replace(' ago', '')
        ))


Creating a temporary SMTP server to 'catch' domain validation emails

One problem that has come up a time or two is dealing with email-based domain validation (specifically in this case for the issuance of TLS certificates) on domains that aren’t actually configured to receive email. Yes, in a perfect world, it would be easier to switch to DNS-based validation (since we have to have control of the DNS for the domain, we need it later), but let’s just assume that’s not an option. So, how do we ‘catch’ the activation email so we can prove we can receive email on that domain?