github.com/lusis/distribution@v2.0.1+incompatible/registry/auth/silly/access.go (about) 1 // Package silly provides a simple authentication scheme that checks for the 2 // existence of an Authorization header and issues access if is present and 3 // non-empty. 4 // 5 // This package is present as an example implementation of a minimal 6 // auth.AccessController and for testing. This is not suitable for any kind of 7 // production security. 8 package silly 9 10 import ( 11 "fmt" 12 "net/http" 13 "strings" 14 15 ctxu "github.com/docker/distribution/context" 16 "github.com/docker/distribution/registry/auth" 17 "golang.org/x/net/context" 18 ) 19 20 // accessController provides a simple implementation of auth.AccessController 21 // that simply checks for a non-empty Authorization header. It is useful for 22 // demonstration and testing. 23 type accessController struct { 24 realm string 25 service string 26 } 27 28 var _ auth.AccessController = &accessController{} 29 30 func newAccessController(options map[string]interface{}) (auth.AccessController, error) { 31 realm, present := options["realm"] 32 if _, ok := realm.(string); !present || !ok { 33 return nil, fmt.Errorf(`"realm" must be set for silly access controller`) 34 } 35 36 service, present := options["service"] 37 if _, ok := service.(string); !present || !ok { 38 return nil, fmt.Errorf(`"service" must be set for silly access controller`) 39 } 40 41 return &accessController{realm: realm.(string), service: service.(string)}, nil 42 } 43 44 // Authorized simply checks for the existence of the authorization header, 45 // responding with a bearer challenge if it doesn't exist. 46 func (ac *accessController) Authorized(ctx context.Context, accessRecords ...auth.Access) (context.Context, error) { 47 req, err := ctxu.GetRequest(ctx) 48 if err != nil { 49 return nil, err 50 } 51 52 if req.Header.Get("Authorization") == "" { 53 challenge := challenge{ 54 realm: ac.realm, 55 service: ac.service, 56 } 57 58 if len(accessRecords) > 0 { 59 var scopes []string 60 for _, access := range accessRecords { 61 scopes = append(scopes, fmt.Sprintf("%s:%s:%s", access.Type, access.Resource.Name, access.Action)) 62 } 63 challenge.scope = strings.Join(scopes, " ") 64 } 65 66 return nil, &challenge 67 } 68 69 return auth.WithUser(ctx, auth.UserInfo{Name: "silly"}), nil 70 } 71 72 type challenge struct { 73 realm string 74 service string 75 scope string 76 } 77 78 func (ch *challenge) ServeHTTP(w http.ResponseWriter, r *http.Request) { 79 header := fmt.Sprintf("Bearer realm=%q,service=%q", ch.realm, ch.service) 80 81 if ch.scope != "" { 82 header = fmt.Sprintf("%s,scope=%q", header, ch.scope) 83 } 84 85 w.Header().Set("WWW-Authenticate", header) 86 w.WriteHeader(http.StatusUnauthorized) 87 } 88 89 func (ch *challenge) Error() string { 90 return fmt.Sprintf("silly authentication challenge: %#v", ch) 91 } 92 93 // init registers the silly auth backend. 94 func init() { 95 auth.Register("silly", auth.InitFunc(newAccessController)) 96 }