...

Source file src/github.com/docker/distribution/registry/auth/silly/access.go

Documentation: github.com/docker/distribution/registry/auth/silly

     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  	"context"
    12  	"fmt"
    13  	"net/http"
    14  	"strings"
    15  
    16  	dcontext "github.com/docker/distribution/context"
    17  	"github.com/docker/distribution/registry/auth"
    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 := dcontext.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  	ctx = auth.WithUser(ctx, auth.UserInfo{Name: "silly"})
    70  	ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, auth.UserNameKey, auth.UserKey))
    71  
    72  	return ctx, nil
    73  
    74  }
    75  
    76  type challenge struct {
    77  	realm   string
    78  	service string
    79  	scope   string
    80  }
    81  
    82  var _ auth.Challenge = challenge{}
    83  
    84  // SetHeaders sets a simple bearer challenge on the response.
    85  func (ch challenge) SetHeaders(r *http.Request, w http.ResponseWriter) {
    86  	header := fmt.Sprintf("Bearer realm=%q,service=%q", ch.realm, ch.service)
    87  
    88  	if ch.scope != "" {
    89  		header = fmt.Sprintf("%s,scope=%q", header, ch.scope)
    90  	}
    91  
    92  	w.Header().Set("WWW-Authenticate", header)
    93  }
    94  
    95  func (ch challenge) Error() string {
    96  	return fmt.Sprintf("silly authentication challenge: %#v", ch)
    97  }
    98  
    99  // init registers the silly auth backend.
   100  func init() {
   101  	auth.Register("silly", auth.InitFunc(newAccessController))
   102  }
   103  

View as plain text