imageserver icon indicating copy to clipboard operation
imageserver copied to clipboard

Implements an HMAC URL signer and verifier with optional time-base expiration

Open cognusion opened this issue 2 years ago • 0 comments

hmac.Signer is an http.Handler that will sign the rest of the URI and parameters, redirecting to the signed URI to prime the cache. So signing request http://localhost:8081/_sign/food/20200723_0017_01.jpg?quality=10 redirects to http://localhost:8081/QfuWvArP9zsFRKwSJuG2MJz4DZsZe2NoVUmy7WBAwaw/food/20200723_0017_01.jpg?expiration=1669988210032&quality=10 (note the hash component and the appended expiration parameter). If any parameters are changed, the hash verification will fail. If the expiration (milliseconds from UNIX epoch) expires, the verification will fail. I can provide a full example if desirable. Happy to iterate on this for a while too if there is feedback.

It can be wired into the groupcache example ala:

func startHTTPServer() {
	http.Handle("/", http.StripPrefix("/", newImageHTTPHandler()))
	if hmacKey != "" {
		hs := hmac.NewSigner([]byte(hmacKey), hmacDuration)
		http.Handle("/_sign/", http.StripPrefix("/_sign/", hs))
	}
	http.Handle("/favicon.ico", http.NotFoundHandler())
	initGroupcacheHTTPPool() // it automatically registers itself to "/_groupcache"
	http.HandleFunc("/stats", groupcacheStatsHTTPHandler)
	err := http.ListenAndServe(flagHTTP, nil)
	if err != nil {
		panic(err)
	}
}

hmac.Parser is a Parser to allow "expiration" to be a valid parameter.

func newImageHTTPHandler() http.Handler {
	return &imageserver_http.Handler{
		Parser: imageserver_http.ListParser([]imageserver_http.Parser{
			&imageserver_http.SourcePathParser{},
			&imageserver_http_crop.Parser{},
			&imageserver_http_gift.RotateParser{},
			&imageserver_http_gift.ResizeParser{},
			&imageserver_http_image.FormatParser{},
			&imageserver_http_image.QualityParser{},
			&hmac.Parser{},
		}),
		Server: newServer(),
	}
}

hmac.Verifier is an imageserver.Server that should be first (aka last) in a composition tree.

func newServer() imageserver.Server {
	srv = newServerImage(srv)
	srv = newServerGroupcache(srv)
	if hmacKey != "" {
		srv = hmac.NewVerifier(srv, hmacKey, hmacDuration)
	}
	return srv
}

cognusion avatar Dec 02 '22 19:12 cognusion