Fix go vet and lint issues

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
Derek McGowan 2015-04-10 16:52:33 -07:00
parent 36d8ce0094
commit 6fd6773b21
6 changed files with 130 additions and 29 deletions

View File

@ -15,8 +15,11 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
const ADDR = ":4443" // ServerAddress is the secure server address to listen on
const DEBUG_ADDR = "localhost:8080" const ServerAddress = ":4443"
// DebugAddress is the debug server address to listen on
const DebugAddress = "localhost:8080"
var debug bool var debug bool
var certFile, keyFile string var certFile, keyFile string
@ -31,8 +34,8 @@ func main() {
flag.Usage = usage flag.Usage = usage
flag.Parse() flag.Parse()
if DEBUG_ADDR != "" { if DebugAddress != "" {
go debugServer(DEBUG_ADDR) go debugServer(DebugAddress)
} }
if certFile == "" || keyFile == "" { if certFile == "" || keyFile == "" {
@ -65,13 +68,13 @@ func main() {
r.Methods("POST").Path("/{imageName}/{tag}").Handler(hand(handlers.AddHandler, utils.SSUpdate)) r.Methods("POST").Path("/{imageName}/{tag}").Handler(hand(handlers.AddHandler, utils.SSUpdate))
server := http.Server{ server := http.Server{
Addr: ADDR, Addr: ServerAddress,
Handler: r, Handler: r,
TLSConfig: tlsConfig, TLSConfig: tlsConfig,
} }
if debug { if debug {
log.Println("[Vetinari Server] : Listening on", ADDR) log.Println("[Vetinari Server] : Listening on", ServerAddress)
} }
err := server.ListenAndServeTLS(certFile, keyFile) err := server.ListenAndServeTLS(certFile, keyFile)
@ -81,7 +84,7 @@ func main() {
} }
func usage() { func usage() {
log.Println(os.Stderr, "usage:", os.Args[0], "<config>") log.Println("usage:", os.Args[0], "<config>")
flag.PrintDefaults() flag.PrintDefaults()
} }

View File

@ -4,6 +4,8 @@ import (
"fmt" "fmt"
) )
// HTTPError represents an application error which will map to
// an HTTP status code and returned error object.
type HTTPError struct { type HTTPError struct {
HTTPStatus int HTTPStatus int
Code int Code int

View File

@ -16,6 +16,7 @@ import (
var db = util.GetSqliteDB() var db = util.GetSqliteDB()
// MainHandler is the default handler for the server
func MainHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request) *errors.HTTPError { func MainHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request) *errors.HTTPError {
if r.Method == "GET" { if r.Method == "GET" {
err := json.NewEncoder(w).Encode("{}") err := json.NewEncoder(w).Encode("{}")
@ -24,7 +25,11 @@ func MainHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request) *er
} }
} else { } else {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
return &errors.HTTPError{http.StatusNotFound, 9999, nil} return &errors.HTTPError{
HTTPStatus: http.StatusNotFound,
Code: 9999,
Err: nil,
}
} }
return nil return nil
} }
@ -40,32 +45,56 @@ func AddHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request) *err
err := decoder.Decode(&meta) err := decoder.Decode(&meta)
defer r.Body.Close() defer r.Body.Close()
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
// add to targets // add to targets
local.AddBlob(vars["tag"], meta) local.AddBlob(vars["tag"], meta)
tufRepo, err := repo.NewRepo(local, "sha256", "sha512") tufRepo, err := repo.NewRepo(local, "sha256", "sha512")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
_ = tufRepo.Init(true) _ = tufRepo.Init(true)
err = tufRepo.AddTarget(vars["tag"], json.RawMessage{}) err = tufRepo.AddTarget(vars["tag"], json.RawMessage{})
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
err = tufRepo.Sign("targets.json") err = tufRepo.Sign("targets.json")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
tufRepo.Snapshot(repo.CompressionTypeNone) tufRepo.Snapshot(repo.CompressionTypeNone)
err = tufRepo.Sign("snapshot.json") err = tufRepo.Sign("snapshot.json")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
tufRepo.Timestamp() tufRepo.Timestamp()
err = tufRepo.Sign("timestamp.json") err = tufRepo.Sign("timestamp.json")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
return nil return nil
} }
@ -79,23 +108,39 @@ func RemoveHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request) *
local.RemoveBlob(vars["tag"]) local.RemoveBlob(vars["tag"])
tufRepo, err := repo.NewRepo(local, "sha256", "sha512") tufRepo, err := repo.NewRepo(local, "sha256", "sha512")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
_ = tufRepo.Init(true) _ = tufRepo.Init(true)
tufRepo.RemoveTarget(vars["tag"]) tufRepo.RemoveTarget(vars["tag"])
err = tufRepo.Sign("targets.json") err = tufRepo.Sign("targets.json")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
tufRepo.Snapshot(repo.CompressionTypeNone) tufRepo.Snapshot(repo.CompressionTypeNone)
err = tufRepo.Sign("snapshot.json") err = tufRepo.Sign("snapshot.json")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
tufRepo.Timestamp() tufRepo.Timestamp()
err = tufRepo.Sign("timestamp.json") err = tufRepo.Sign("timestamp.json")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
return nil return nil
} }
@ -109,12 +154,17 @@ func GetHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request) *err
meta, err := local.GetMeta() meta, err := local.GetMeta()
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
w.Write(meta[vars["tufFile"]]) w.Write(meta[vars["tufFile"]])
return nil return nil
} }
// GenKeysHandler is the handler for generate keys endpoint
func GenKeysHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request) *errors.HTTPError { func GenKeysHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request) *errors.HTTPError {
log.Printf("GenKeysHandler") log.Printf("GenKeysHandler")
// remove tag from tagets list // remove tag from tagets list
@ -122,7 +172,11 @@ func GenKeysHandler(ctx utils.IContext, w http.ResponseWriter, r *http.Request)
local := store.DBStore(db, vars["imageName"]) local := store.DBStore(db, vars["imageName"])
tufRepo, err := repo.NewRepo(local, "sha256", "sha512") tufRepo, err := repo.NewRepo(local, "sha256", "sha512")
if err != nil { if err != nil {
return &errors.HTTPError{http.StatusInternalServerError, 9999, err} return &errors.HTTPError{
HTTPStatus: http.StatusInternalServerError,
Code: 9999,
Err: err,
}
} }
tufRepo.GenKey("root") tufRepo.GenKey("root")
tufRepo.GenKey("targets") tufRepo.GenKey("targets")

View File

@ -1,10 +1,12 @@
package utils package utils
// IScope is an identifier scope
type IScope interface { type IScope interface {
ID() string ID() string
Compare(IScope) bool Compare(IScope) bool
} }
// IAuthorizer is an interfaces to authorize a scope
type IAuthorizer interface { type IAuthorizer interface {
// Authorize is expected to set the Authorization on the Context. If // Authorize is expected to set the Authorization on the Context. If
// Authorization fails, an error should be returned, but additionally, // Authorization fails, an error should be returned, but additionally,
@ -13,6 +15,8 @@ type IAuthorizer interface {
Authorize(IContext, ...IScope) error Authorize(IContext, ...IScope) error
} }
// IAuthorization is an interface to determine whether
// an object has a scope
type IAuthorization interface { type IAuthorization interface {
HasScope(IScope) bool HasScope(IScope) bool
} }
@ -21,46 +25,66 @@ type IAuthorization interface {
// THESE ARE FOR DEV PURPOSES ONLY, DO NOT USE IN // THESE ARE FOR DEV PURPOSES ONLY, DO NOT USE IN
// PRODUCTION // PRODUCTION
// DON'T USE THIS FOR ANYTHING, IT'S VERY INSECURE // InsecureAuthorizer is an insecure implementation of IAuthorizer.
// WARNING: DON'T USE THIS FOR ANYTHING, IT'S VERY INSECURE
type InsecureAuthorizer struct{} type InsecureAuthorizer struct{}
// LIKE I SAID, VERY INSECURE // Authorize authorizes any scope
// WARNING: LIKE I SAID, VERY INSECURE
func (auth *InsecureAuthorizer) Authorize(ctx IContext, scopes ...IScope) error { func (auth *InsecureAuthorizer) Authorize(ctx IContext, scopes ...IScope) error {
ctx.SetAuthorization(&InsecureAuthorization{}) ctx.SetAuthorization(&InsecureAuthorization{})
return nil return nil
} }
// ALSO DON'T USE THIS, IT'S ALSO VERY INSECURE // InsecureAuthorization is an implementation of IAuthorization
// which will consider any scope authorized.
// WARNING: ALSO DON'T USE THIS, IT'S ALSO VERY INSECURE
type InsecureAuthorization struct { type InsecureAuthorization struct {
} }
// THIS IS JUST INCREDIBLY INSECURE // HasScope always returns true for any scope
// WARNING: THIS IS JUST INCREDIBLY INSECURE
func (authzn *InsecureAuthorization) HasScope(scope IScope) bool { func (authzn *InsecureAuthorization) HasScope(scope IScope) bool {
return true return true
} }
// ### END INSECURE AUTHORIZATION TOOLS ### // ### END INSECURE AUTHORIZATION TOOLS ###
// NoAuthorization is an implementation of IAuthorization
// which never allows a scope to be valid.
type NoAuthorization struct{} type NoAuthorization struct{}
// HasScope returns false for any scope
func (authzn *NoAuthorization) HasScope(scope IScope) bool { func (authzn *NoAuthorization) HasScope(scope IScope) bool {
return false return false
} }
// SimpleScope is a simple scope represented by a string.
type SimpleScope string type SimpleScope string
// ID returns the string representing the scope.
func (ss SimpleScope) ID() string { func (ss SimpleScope) ID() string {
return string(ss) return string(ss)
} }
// Compare compares to the given scope for equality.
func (ss SimpleScope) Compare(toCompare IScope) bool { func (ss SimpleScope) Compare(toCompare IScope) bool {
return ss.ID() == toCompare.ID() return ss.ID() == toCompare.ID()
} }
const ( const (
// SSNoAuth is the simple scope "NoAuth"
SSNoAuth SimpleScope = SimpleScope("NoAuth") SSNoAuth SimpleScope = SimpleScope("NoAuth")
SSCreate = SimpleScope("Create")
SSRead = SimpleScope("Read") // SSCreate is the simple scope "Create"
SSUpdate = SimpleScope("Update") SSCreate = SimpleScope("Create")
SSDelete = SimpleScope("Delete")
// SSRead is the simple scope "Read"
SSRead = SimpleScope("Read")
// SSUpdate is the simple scope "Update"
SSUpdate = SimpleScope("Update")
// SSDelete is the simple scope "Delete"
SSDelete = SimpleScope("Delete")
) )

View File

@ -4,6 +4,7 @@ import (
"net/http" "net/http"
) )
// IContext defines an interface for managing authorizations.
type IContext interface { type IContext interface {
// TODO: define a set of standard getters. Using getters // TODO: define a set of standard getters. Using getters
// will allow us to easily and transparently cache // will allow us to easily and transparently cache
@ -24,27 +25,36 @@ type IContext interface {
SetAuthorization(IAuthorization) SetAuthorization(IAuthorization)
} }
// IContextFactory creates a IContext from an http request.
type IContextFactory func(*http.Request) IContext type IContextFactory func(*http.Request) IContext
// Context represents an authorization context for a resource.
type Context struct { type Context struct {
resource string resource string
authorization IAuthorization authorization IAuthorization
} }
// ContextFactory creates a new authorization context with the
// given HTTP request path as the resource.
func ContextFactory(r *http.Request) IContext { func ContextFactory(r *http.Request) IContext {
return &Context{ return &Context{
resource: r.URL.Path, resource: r.URL.Path,
} }
} }
// Resource returns the resource value for the context.
func (ctx *Context) Resource() string { func (ctx *Context) Resource() string {
return ctx.resource return ctx.resource
} }
// Authorization returns an IAuthorization implementation for
// the context.
func (ctx *Context) Authorization() IAuthorization { func (ctx *Context) Authorization() IAuthorization {
return ctx.authorization return ctx.authorization
} }
// SetAuthorization allows setting an IAuthorization for
// the context.
func (ctx *Context) SetAuthorization(authzn IAuthorization) { func (ctx *Context) SetAuthorization(authzn IAuthorization) {
ctx.authorization = authzn ctx.authorization = authzn
} }

View File

@ -1,4 +1,3 @@
// http.go contains useful http utilities.
package utils package utils
import ( import (
@ -7,8 +6,12 @@ import (
"github.com/docker/vetinari/errors" "github.com/docker/vetinari/errors"
) )
// BetterHandler defines an alterate HTTP handler interface which takes in
// a context for authorization and returns an HTTP application error.
type BetterHandler func(ctx IContext, w http.ResponseWriter, r *http.Request) *errors.HTTPError type BetterHandler func(ctx IContext, w http.ResponseWriter, r *http.Request) *errors.HTTPError
// RootHandler is an implementation of an HTTP request handler which handles
// authorization and calling out to the defined alternate http handler.
type RootHandler struct { type RootHandler struct {
handler BetterHandler handler BetterHandler
auth IAuthorizer auth IAuthorizer
@ -16,12 +19,17 @@ type RootHandler struct {
context IContextFactory context IContextFactory
} }
// RootHandlerFactory creates a new RootHandler factory using the given
// Context creator and authorizer. The returned factory allows creating
// new RootHandlers from the alternate http handler BetterHandler and
// a scope.
func RootHandlerFactory(auth IAuthorizer, ctxFac IContextFactory) func(BetterHandler, ...IScope) *RootHandler { func RootHandlerFactory(auth IAuthorizer, ctxFac IContextFactory) func(BetterHandler, ...IScope) *RootHandler {
return func(handler BetterHandler, scopes ...IScope) *RootHandler { return func(handler BetterHandler, scopes ...IScope) *RootHandler {
return &RootHandler{handler, auth, scopes, ctxFac} return &RootHandler{handler, auth, scopes, ctxFac}
} }
} }
// ServeHTTP serves an HTTP request and implements the http.Handler interface.
func (root *RootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (root *RootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := root.context(r) ctx := root.context(r)
if err := root.auth.Authorize(ctx, root.scopes...); err != nil { if err := root.auth.Authorize(ctx, root.scopes...); err != nil {