1
package identityservice
9
"gopkg.in/goose.v1/testservices/hook"
12
// Implement the v2 Key Pair form of identity based on Keystone
14
type KeyPairRequest struct {
16
ApiAccessKeyCredentials struct {
17
AccessKey string `json:"accessKey"`
18
SecretKey string `json:"secretKey"`
19
} `json:"apiAccessKeyCredentials"`
20
TenantName string `json:"tenantName"`
30
func NewKeyPair() *KeyPair {
33
users: make(map[string]UserInfo),
34
tenants: make(map[string]string),
39
func (u *KeyPair) RegisterServiceProvider(name, serviceType string, serviceProvider ServiceProvider) {
40
service := V2Service{name, serviceType, serviceProvider.Endpoints()}
41
u.AddService(Service{V2: service})
44
func (u *KeyPair) AddService(service Service) {
45
u.services = append(u.services, service.V2)
48
func (u *KeyPair) ReturnFailure(w http.ResponseWriter, status int, message string) {
53
Title: http.StatusText(status),
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)
61
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(content)))
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)
75
if content, err := ioutil.ReadAll(r.Body); err != nil {
76
w.WriteHeader(http.StatusBadRequest)
79
if err := json.Unmarshal(content, &req); err != nil {
80
u.ReturnFailure(w, http.StatusBadRequest, notJSON)
84
userInfo, errmsg := u.authenticate(req.Auth.ApiAccessKeyCredentials.AccessKey, req.Auth.ApiAccessKeyCredentials.SecretKey)
86
u.ReturnFailure(w, http.StatusUnauthorized, errmsg)
89
res, err := u.generateAccessResponse(userInfo)
91
u.ReturnFailure(w, http.StatusInternalServerError, err.Error())
94
content, err := json.Marshal(res)
96
u.ReturnFailure(w, http.StatusInternalServerError, err.Error())
99
w.WriteHeader(http.StatusOK)
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 {
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 {
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)