0
Fork 0
mirror of https://github.com/willnorris/imageproxy.git synced 2024-12-16 21:56:43 -05:00

add support for multiple signature keys (#209)

This commit is contained in:
Mauro Ciancio 2020-02-01 22:03:59 -03:00 committed by GitHub
parent 3bdd0fe8ed
commit ef09c1ba31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 21 deletions

View file

@ -48,7 +48,7 @@ var denyHosts = flag.String("denyHosts", "", "comma separated list of denied rem
var referrers = flag.String("referrers", "", "comma separated list of allowed referring hosts")
var baseURL = flag.String("baseURL", "", "default base URL for relative remote URLs")
var cache tieredCache
var signatureKey = flag.String("signatureKey", "", "HMAC key used in calculating request signatures")
var signatureKeyList SignatureKeyList
var scaleUp = flag.Bool("scaleUp", false, "allow images to scale beyond their original dimensions")
var timeout = flag.Duration("timeout", 0, "time limit for requests served by this proxy")
var verbose = flag.Bool("verbose", false, "print verbose logging messages")
@ -58,6 +58,7 @@ var userAgent = flag.String("userAgent", "willnorris/imageproxy", "specify the u
func init() {
flag.Var(&cache, "cache", "location to cache images (see https://github.com/willnorris/imageproxy#cache)")
flag.Var(&signatureKeyList, "signatureKey", "HMAC key used in calculating request signatures")
}
func main() {
@ -77,18 +78,7 @@ func main() {
if *contentTypes != "" {
p.ContentTypes = strings.Split(*contentTypes, ",")
}
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
}
p.SignatureKeys = signatureKeyList
if *baseURL != "" {
var err error
p.DefaultBaseURL, err = url.Parse(*baseURL)
@ -112,6 +102,27 @@ func main() {
log.Fatal(http.ListenAndServe(*addr, nil))
}
type SignatureKeyList [][]byte
func (skl *SignatureKeyList) String() string {
return fmt.Sprint(*skl)
}
func (skl *SignatureKeyList) Set(value string) error {
key := []byte(value)
if strings.HasPrefix(value, "@") {
file := strings.TrimPrefix(value, "@")
var err error
key, err = ioutil.ReadFile(file)
if err != nil {
log.Fatalf("error reading signature file: %v", err)
}
}
*skl = append(*skl, key)
return nil
}
// tieredCache allows specifying multiple caches via flags, which will create
// tiered caches using the twotier package.
type tieredCache struct {

View file

@ -64,8 +64,9 @@ type Proxy struct {
// The Logger used by the image proxy
Logger *log.Logger
// SignatureKey is the HMAC key used to verify signed requests.
SignatureKey []byte
// SignatureKeys is a list of HMAC keys used to verify signed requests.
// Any of them can be used to verify signed requests.
SignatureKeys [][]byte
// Allow images to scale beyond their original dimensions.
ScaleUp bool
@ -258,7 +259,7 @@ func (p *Proxy) allowed(r *Request) error {
return errDeniedHost
}
if len(p.AllowHosts) == 0 && len(p.SignatureKey) == 0 {
if len(p.AllowHosts) == 0 && len(p.SignatureKeys) == 0 {
return nil // no allowed hosts or signature key, all requests accepted
}
@ -266,8 +267,10 @@ func (p *Proxy) allowed(r *Request) error {
return nil
}
if len(p.SignatureKey) > 0 && validSignature(p.SignatureKey, r) {
return nil
for _, signatureKey := range p.SignatureKeys {
if len(signatureKey) > 0 && validSignature(signatureKey, r) {
return nil
}
}
return errNotAllowed

View file

@ -116,7 +116,13 @@ func TestCopyHeader(t *testing.T) {
func TestAllowed(t *testing.T) {
allowHosts := []string{"good"}
key := []byte("c0ffee")
key := [][]byte{
[]byte("c0ffee"),
}
multipleKey := [][]byte{
[]byte("c0ffee"),
[]byte("beer"),
}
genRequest := func(headers map[string]string) *http.Request {
req := &http.Request{Header: make(http.Header)}
@ -132,7 +138,7 @@ func TestAllowed(t *testing.T) {
allowHosts []string
denyHosts []string
referrers []string
key []byte
keys [][]byte
request *http.Request
allowed bool
}{
@ -151,7 +157,10 @@ func TestAllowed(t *testing.T) {
// signature key
{"http://test/image", Options{Signature: "NDx5zZHx7QfE8E-ijowRreq6CJJBZjwiRfOVk_mkfQQ="}, nil, nil, nil, key, nil, true},
{"http://test/image", Options{Signature: "NDx5zZHx7QfE8E-ijowRreq6CJJBZjwiRfOVk_mkfQQ="}, nil, nil, nil, multipleKey, nil, true}, // signed with key "c0ffee"
{"http://test/image", Options{Signature: "FWIawYV4SEyI4zKJMeGugM-eJM1eI_jXPEQ20ZgRe4A="}, nil, nil, nil, multipleKey, nil, true}, // signed with key "beer"
{"http://test/image", Options{Signature: "deadbeef"}, nil, nil, nil, key, nil, false},
{"http://test/image", Options{Signature: "deadbeef"}, nil, nil, nil, multipleKey, nil, false},
{"http://test/image", emptyOptions, nil, nil, nil, key, nil, false},
// allowHosts and signature
@ -169,7 +178,7 @@ func TestAllowed(t *testing.T) {
p := NewProxy(nil, nil)
p.AllowHosts = tt.allowHosts
p.DenyHosts = tt.denyHosts
p.SignatureKey = tt.key
p.SignatureKeys = tt.keys
p.Referrers = tt.referrers
u, err := url.Parse(tt.url)