Skip to content

Commit

Permalink
add signature key flag to imageproxy command
Browse files Browse the repository at this point in the history
  • Loading branch information
willnorris committed May 14, 2015
1 parent a9efefc commit 7a0f78f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 8 deletions.
52 changes: 44 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ image horizontally. Images are flipped **after** being resized and rotated.
The `q{percentage}` option can be used to specify the output quality (JPEG
only). If not specified, the default value of `95` is used.

#### Signature ####

The `s{signature}` option specifies an optional base64 encoded HMAC used to
sign the remote URL in the request. The HMAC key used to verify signatures is
provided to the imageproxy server on startup.

### Remote URL ###

The URL of the original image to load is specified as the remainder of the
Expand Down Expand Up @@ -129,10 +135,11 @@ unbounded. To cache images on disk instead, include the `cacheDir` flag:

imageproxy -cacheDir /tmp/imageproxy

Reload the [codercat URL](http://localhost:8080/500/https://octodex.github.com/images/codercat.jpg),
and then inspect the contents of `/tmp/imageproxy`. There should be two files
there, one for the original full-size codercat image, and one for the resized
500px version.
Reload the [codercat URL][], and then inspect the contents of
`/tmp/imageproxy`. There should be two files there, one for the original
full-size codercat image, and one for the resized 500px version.

[codercat URL]: http://localhost:8080/500/https://octodex.github.com/images/codercat.jpg

### Host whitelist ###

Expand All @@ -144,10 +151,39 @@ running:

imageproxy -whitelist example.com

Reload the [codercat URL](http://localhost:8080/500/https://octodex.github.com/images/codercat.jpg),
and you should now get an error message. You can specify multiple hosts as a
comma separated list, or prefix a host value with `*.` to allow all sub-domains
as well.
Reload the [codercat URL][], and you should now get an error message. You can
specify multiple hosts as a comma separated list, or prefix a host value with
`*.` to allow all sub-domains as well.

### Signed Requests ###

Instead of a host whitelist, you can require that requests be signed. This is
useful in preventing abuse when you don't have just a static list of hosts you
want to allow. Signatures are generated using HMAC-SHA256 against the remote
URL, and url-safe base64 encoding the result:

base64urlencode(hmac.New(sha256, <key>).digest(<remote_url>))

The HMAC key is specified using the `signatureKey` flag. If this flag
begins with an "@", the remainder of the value is interpreted as a file on disk
which contains the HMAC key.

Try it out by running:

imageproxy -signatureKey "secret key"

Reload the [codercat URL][], and you should see an error message. Now load a
[signed codercat URL][] and verify that it loads properly.

[signed codercat URL]: http://localhost:8080/500,sXyMwWKIC5JPCtlYOQ2f4yMBTqpjtUsfI67Sp7huXIYY=/https://octodex.github.com/images/codercat.jpg

Some simple code samples for generating signatures in various languages can be
found starting in [this comment](https://github.com/willnorris/imageproxy/issues/11#issuecomment-101428470).

If both a whiltelist and signatureKey are specified, requests can match either.
In other words, requests that match one of the whitelisted hosts don't
necessarily need to be signed, though they can be.


Run `imageproxy -help` for a complete list of flags the command accepts. If
you want to use a different caching implementation, it's probably easiest to
Expand Down
14 changes: 14 additions & 0 deletions cmd/imageproxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
Expand All @@ -43,6 +44,7 @@ var whitelist = flag.String("whitelist", "", "comma separated list of allowed re
var baseURL = flag.String("baseURL", "", "default base URL for relative remote URLs")
var cacheDir = flag.String("cacheDir", "", "directory to use for file cache")
var cacheSize = flag.Uint64("cacheSize", 100, "maximum size of file cache (in MB)")
var signatureKey = flag.String("signatureKey", "", "HMAC key used in calculating request signatures")
var version = flag.Bool("version", false, "print version information")

func main() {
Expand All @@ -68,6 +70,18 @@ func main() {
if *whitelist != "" {
p.Whitelist = strings.Split(*whitelist, ",")
}
if *signatureKey != "" {
key := []byte(*signatureKey)
if strings.HasPrefix(*signatureKey, "@") {
file := strings.TrimPrefix(*signatureKey, "@")
var err error
key, err = ioutil.ReadFile(file)
if err != nil {
log.Fatalf("error reading signature file: %v", err)
}
}
p.SignatureKey = key
}
if *baseURL != "" {
var err error
p.DefaultBaseURL, err = url.Parse(*baseURL)
Expand Down

0 comments on commit 7a0f78f

Please sign in to comment.