gopkg.in/goose.v2@v2.0.1/testservices/identityservice/keypair.go (about)

     1  package identityservice
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  
     9  	"gopkg.in/goose.v2/testservices/hook"
    10  )
    11  
    12  // Implement the v2 Key Pair form of identity based on Keystone
    13  
    14  type KeyPairRequest struct {
    15  	Auth struct {
    16  		ApiAccessKeyCredentials struct {
    17  			AccessKey string `json:"accessKey"`
    18  			SecretKey string `json:"secretKey"`
    19  		} `json:"apiAccessKeyCredentials"`
    20  		TenantName string `json:"tenantName"`
    21  	} `json:"auth"`
    22  }
    23  
    24  type KeyPair struct {
    25  	hook.TestService
    26  	Users
    27  	services []V2Service
    28  }
    29  
    30  func NewKeyPair() *KeyPair {
    31  	return &KeyPair{
    32  		Users: Users{
    33  			users:   make(map[string]UserInfo),
    34  			tenants: make(map[string]string),
    35  		},
    36  	}
    37  }
    38  
    39  func (u *KeyPair) RegisterServiceProvider(name, serviceType string, serviceProvider ServiceProvider) {
    40  	service := V2Service{name, serviceType, serviceProvider.Endpoints()}
    41  	u.AddService(Service{V2: service})
    42  }
    43  
    44  func (u *KeyPair) AddService(service Service) {
    45  	u.services = append(u.services, service.V2)
    46  }
    47  
    48  func (u *KeyPair) ReturnFailure(w http.ResponseWriter, status int, message string) {
    49  	e := ErrorWrapper{
    50  		Error: ErrorResponse{
    51  			Message: message,
    52  			Code:    status,
    53  			Title:   http.StatusText(status),
    54  		},
    55  	}
    56  	if content, err := json.Marshal(e); err != nil {
    57  		w.Header().Set("Content-Length", fmt.Sprintf("%d", len(internalError)))
    58  		w.WriteHeader(http.StatusInternalServerError)
    59  		w.Write(internalError)
    60  	} else {
    61  		w.Header().Set("Content-Length", fmt.Sprintf("%d", len(content)))
    62  		w.WriteHeader(status)
    63  		w.Write(content)
    64  	}
    65  }
    66  
    67  func (u *KeyPair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    68  	var req KeyPairRequest
    69  	// Testing against Canonistack, all responses are application/json, even failures
    70  	w.Header().Set("Content-Type", "application/json")
    71  	if r.Header.Get("Content-Type") != "application/json" {
    72  		u.ReturnFailure(w, http.StatusBadRequest, notJSON)
    73  		return
    74  	}
    75  	if content, err := ioutil.ReadAll(r.Body); err != nil {
    76  		w.WriteHeader(http.StatusBadRequest)
    77  		return
    78  	} else {
    79  		if err := json.Unmarshal(content, &req); err != nil {
    80  			u.ReturnFailure(w, http.StatusBadRequest, notJSON)
    81  			return
    82  		}
    83  	}
    84  	userInfo, errmsg := u.authenticate(req.Auth.ApiAccessKeyCredentials.AccessKey, req.Auth.ApiAccessKeyCredentials.SecretKey, "default")
    85  	if errmsg != "" {
    86  		u.ReturnFailure(w, http.StatusUnauthorized, errmsg)
    87  		return
    88  	}
    89  	res, err := u.generateAccessResponse(userInfo)
    90  	if err != nil {
    91  		u.ReturnFailure(w, http.StatusInternalServerError, err.Error())
    92  		return
    93  	}
    94  	content, err := json.Marshal(res)
    95  	if err != nil {
    96  		u.ReturnFailure(w, http.StatusInternalServerError, err.Error())
    97  		return
    98  	}
    99  	w.WriteHeader(http.StatusOK)
   100  	w.Write(content)
   101  }
   102  
   103  func (u *KeyPair) generateAccessResponse(userInfo *UserInfo) (*AccessResponse, error) {
   104  	res := AccessResponse{}
   105  	// We pre-populate the response with genuine entries so that it looks sane.
   106  	if err := json.Unmarshal([]byte(exampleResponse), &res); err != nil {
   107  		return nil, err
   108  	}
   109  	res.Access.ServiceCatalog = u.services
   110  	res.Access.Token.Id = userInfo.Token
   111  	res.Access.Token.Tenant.Id = userInfo.TenantId
   112  	res.Access.User.Id = userInfo.Id
   113  	if err := u.ProcessControlHook("authorisation", u, &res, userInfo); err != nil {
   114  		return nil, err
   115  	}
   116  	return &res, nil
   117  }
   118  
   119  // setupHTTP attaches all the needed handlers to provide the HTTP API.
   120  func (u *KeyPair) SetupHTTP(mux *http.ServeMux) {
   121  	mux.Handle("/tokens", u)
   122  }
   123  
   124  func (u *KeyPair) Stop() {
   125  	// noop
   126  }