Address auth package comments from stevvooe
Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
This commit is contained in:
parent
88de2e11fb
commit
d30a8321d8
4 changed files with 44 additions and 23 deletions
51
auth/auth.go
51
auth/auth.go
|
@ -1,3 +1,33 @@
|
|||
// Package auth defines a standard interface for request access controllers.
|
||||
//
|
||||
// An access controller has a simple interface with a single `Authorized`
|
||||
// method which checks that a given request is authorized to perform one or
|
||||
// more actions on one or more resources. This method should return a non-nil
|
||||
// error if the requset is not authorized.
|
||||
//
|
||||
// An implementation registers its access controller by name with a constructor
|
||||
// which accepts an options map for configuring the access controller.
|
||||
//
|
||||
// options := map[string]interface{}{"sillySecret": "whysosilly?"}
|
||||
// accessController, _ := auth.GetAccessController("silly", options)
|
||||
//
|
||||
// This `accessController` can then be used in a request handler like so:
|
||||
//
|
||||
// func updateOrder(w http.ResponseWriter, r *http.Request) {
|
||||
// orderNumber := r.FormValue("orderNumber")
|
||||
// resource := auth.Resource{Type: "customerOrder", Name: orderNumber}
|
||||
// access := auth.Access{Resource: resource, Action: "update"}
|
||||
//
|
||||
// if err := accessController.Authorized(r, access); err != nil {
|
||||
// if challenge, ok := err.(auth.Challenge) {
|
||||
// // Let the challenge write the response.
|
||||
// challenge.ServeHTTP(w, r)
|
||||
// } else {
|
||||
// // Some other error.
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
package auth
|
||||
|
||||
import (
|
||||
|
@ -23,8 +53,11 @@ type Access struct {
|
|||
// header values based on the error.
|
||||
type Challenge interface {
|
||||
error
|
||||
Status() int
|
||||
SetHeader(header http.Header)
|
||||
// ServeHTTP prepares the request to conduct the appropriate challenge
|
||||
// response. For most implementations, simply calling ServeHTTP should be
|
||||
// sufficient. Because no body is written, users may write a custom body after
|
||||
// calling ServeHTTP, but any headers must be written before the call and may
|
||||
// be overwritten.
|
||||
ServeHTTP(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
|
@ -32,14 +65,12 @@ type Challenge interface {
|
|||
// and required access levels for a request. Implementations can support both
|
||||
// complete denial and http authorization challenges.
|
||||
type AccessController interface {
|
||||
// Authorized returns non-nil if the request is granted the request
|
||||
// access. If the error is non-nil, access should always be denied. The
|
||||
// error may be of type Challenge, in which case the caller may have the
|
||||
// Challenge handle the request or choose what action to take based on the
|
||||
// Challenge header or response status.
|
||||
//
|
||||
// In the future, other error types, besides Challenge, may be added to
|
||||
// support more complex authorization flows.
|
||||
// Authorized returns non-nil if the request is granted access. If one or
|
||||
// more Access structs are provided, the requested access will be compared
|
||||
// with what is available to the request. If the error is non-nil, access
|
||||
// should always be denied. The error may be of type Challenge, in which
|
||||
// case the caller may have the Challenge handle the request or choose
|
||||
// what action to take based on the Challenge header or response status.
|
||||
Authorized(req *http.Request, access ...Access) error
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ func (ac *authChallenge) challengeParams() string {
|
|||
|
||||
// SetHeader sets the WWW-Authenticate value for the given header.
|
||||
func (ac *authChallenge) SetHeader(header http.Header) {
|
||||
header.Add(http.CanonicalHeaderKey("WWW-Authenticate"), ac.challengeParams())
|
||||
header.Add("WWW-Authenticate", ac.challengeParams())
|
||||
}
|
||||
|
||||
// ServeHttp handles writing the challenge response
|
||||
|
|
|
@ -80,7 +80,6 @@ type Token struct {
|
|||
Header *Header
|
||||
Claims *ClaimSet
|
||||
Signature []byte
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// VerifyOptions is used to specify
|
||||
|
@ -150,11 +149,6 @@ func NewToken(rawToken string) (*Token, error) {
|
|||
// Verify attempts to verify this token using the given options.
|
||||
// Returns a nil error if the token is valid.
|
||||
func (t *Token) Verify(verifyOpts VerifyOptions) error {
|
||||
if t.Valid {
|
||||
// Token was already verified.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify that the Issuer claim is a trusted authority.
|
||||
if !verifyOpts.TrustedIssuers.Contains(t.Claims.Issuer) {
|
||||
log.Errorf("token from untrusted issuer: %q", t.Claims.Issuer)
|
||||
|
@ -203,8 +197,8 @@ func (t *Token) Verify(verifyOpts VerifyOptions) error {
|
|||
|
||||
// Next, check if the signing key is one of the trusted keys.
|
||||
if _, isTrustedKey := verifyOpts.TrustedKeys[signingKey.KeyID()]; isTrustedKey {
|
||||
// We're done! The token was signed by a trusted key and has been verified!
|
||||
t.Valid = true
|
||||
// We're done! The token was signed by
|
||||
// a trusted key and has been verified!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -301,7 +295,6 @@ func (t *Token) verifyCertificateChain(leafKey libtrust.PublicKey, roots *x509.C
|
|||
}
|
||||
|
||||
// The signing key's x509 chain is valid!
|
||||
t.Valid = true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -206,9 +206,6 @@ func TestTokenVerify(t *testing.T) {
|
|||
if err := token.Verify(verifyOps); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !token.Valid {
|
||||
t.Fatal("token not marked as Valid")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue