Sam Merritt

torgomatic

An Introduction to TempURL in OpenStack Swift

TempURL is a middleware for Swift that lets you grant temporary access to particular objects. This post is intended to show how TempURL works and get you started using it.

Set Up Your Account

TempURL works by adding a signature to the URL based on a shared secret. So, to use TempURL, you need to tell Swift what the value of that secret is. That’s easy; it’s just a particular piece of metadata on your Swift account. Make up a secret to use (any string will do), and set it as the value of X-Account-Meta-Temp-Url-Key. Here’s some examples:

python-swiftclient
1
2
# (Assuming that $ST_AUTH, $ST_USER, and $ST_KEY are set in the environment)
$ swift post -m Temp-Url-Key:correcthorsebatterystaple
curl
1
2
3
$ curl -X POST -H "X-Auth-Token: $AUTH_TOKEN" \
    -H "X-Account-Meta-Temp-Url-Key: correcthorsebatterystaple" \
    https://swiftcluster/v1/myaccount
pyrax
1
2
3
import pyrax
pyrax.set_credential_file("~/.rackspace-pyrax-creds")   # or however you like to do auth
pyrax.cloudfiles.set_account_metadata('temp-url-key', 'correcthorsebatterystaple')

Set Up Your Swift Cluster

If you’re not operating a Swift cluster, skip to the next section, as this doesn’t apply to you.

TempURL is part of Swift, so the code is already on your cluster. To enable it, make sure that it’s in your proxy server’s middleware pipeline.

/etc/swift/proxy-server.conf
1
2
3
4
5
6
[pipeline:main]
pipeline = proxy-logging healthcheck cache tempurl tempauth proxy-logging proxy-server

[filter:tempurl]
use = egg:swift#tempurl
methods = GET HEAD PUT DELETE POST

This configuration enables all the HTTP verbs. For historical reasons, the default set of allowed methods is only GET, HEAD, and PUT. However, I can’t think of any reason not to let your users use whatever HTTP verbs they want.

Signing URLs

A URL’s signature is derived from four things:

  • the URL’s path component (e.g. “/v1/AUTH_myusername/gutenberg/beowulf.epub”)
  • the expiration time as a Unix timestamp (e.g. 1368056658 for 2013-05-08T23:44:18Z)
  • the HTTP verb (e.g. GET, POST)
  • the shared secret

The signature is the HMAC-SHA1 of the method, the expiration time, and the path, separated by newlines. The shared secret is the HMAC key.

Since that’s technically correct but completely impenetrable, let’s see an example.

Signing a URL
1
2
3
4
5
6
7
8
9
10
11
12
13
import hashlib
import hmac
import time

method, path = 'GET', '/v1/AUTH_myusername/gutenberg/beowulf.epub'
expiration = int(time.time() + 1800)  # valid until half an hour from now
shared_secret = 'correcthorsebatterystaple'

hmac_body = "\n".join([method, expiration, path])
sig = hmac.new(shared_secret, hmac_body, hashlib.sha1).hexdigest()

signed_url = "https://swift/{path}?temp_url_sig={sig}&temp_url_expires={exp}".format(
    path=path, sig=sig, exp=expiration)

If you don’t feel like writing your own URL signer, Swift comes with a utility called swift-temp-url that does just what the name implies. It’s really simple to use:

Signing with swift-temp-url
1
2
3
$ swift-temp-url GET 1800 /v1/AUTH_myusername/gutenberg/beowulf.epub correcthorsebatterystaple
/v1/AUTH_myusername/gutenberg/beowulf.epub?temp_url_sig=cf62879f772eaf73c86c2f3bc8b6a4cfd94d4125&temp_url_expires=1368059214
$ 

That’s all there is to using TempURL. In future posts, I’ll explore just a few of the awesome things you can do with signed URLs.