1
package identityservice
10
"gopkg.in/goose.v1/testservices/hook"
13
// V3UserPassRequest Implement the v3 User Pass form of identity (Keystone)
14
type V3UserPassRequest struct {
17
Methods []string `json:"methods"`
20
Name string `json:"name"`
21
Password string `json:"password"`
27
Name string `json:"name"`
33
// V3Endpoint represents endpoints to a Service
34
type V3Endpoint struct {
35
Interface string `json:"interface"`
36
RegionID string `json:"region_id"`
37
URL string `json:"url"`
40
// NewV3Endpoints returns an array of V3Endpoint for the given Region and the
41
// passed admin, internal and public URLs.
42
func NewV3Endpoints(adminURL, internalURL, publicURL, regionID string) []V3Endpoint {
45
eps = append(eps, V3Endpoint{
51
if internalURL != "" {
52
eps = append(eps, V3Endpoint{
54
Interface: "internal",
59
eps = append(eps, V3Endpoint{
69
// V3Service represents an OpenStack web service that you can access through a URL.
70
type V3Service struct {
72
Name string `json:"name"`
73
Type string `json:"type"`
74
Endpoints []V3Endpoint `json:"endpoints"`
77
// V3TokenResponse repesent a Token returned as a response to authentication to
79
type V3TokenResponse struct {
80
Expires time.Time `json:"expires_at"`
81
Issued time.Time `json:"issued_at"`
82
Methods []string `json:"methods"`
83
Catalog []V3Service `json:"catalog,omitempty"`
84
Project *V3Project `json:"project,omitempty"`
87
Name string `json:"name"`
91
// V3Project represent an openstack project, A project is the base unit of ownership.
92
// Resources are owned by a specific project. A project is owned by a specific domain.
93
type V3Project struct {
94
ID string `json:"id,omitempty"`
97
// V3UserPass represents an authenticated user to a service.
98
type V3UserPass struct {
104
// NewV3UserPass returns a new V3UserPass
105
func NewV3UserPass() *V3UserPass {
106
userpass := &V3UserPass{
107
services: make([]V3Service, 0),
109
userpass.users = make(map[string]UserInfo)
110
userpass.tenants = make(map[string]string)
114
// RegisterServiceProvider registers V3UserPass as a service provider.
115
func (u *V3UserPass) RegisterServiceProvider(name, serviceType string, serviceProvider ServiceProvider) {
116
service := V3Service{
120
Endpoints: serviceProvider.V3Endpoints(),
122
u.AddService(Service{V3: service})
125
// AddService adds a service to the current V3UserPass.
126
func (u *V3UserPass) AddService(service Service) {
127
u.services = append(u.services, service.V3)
130
// ReturnFailure wraps and returns an error through the http connection.
131
func (u *V3UserPass) ReturnFailure(w http.ResponseWriter, status int, message string) {
133
Error: ErrorResponse{
136
Title: http.StatusText(status),
139
if content, err := json.Marshal(e); err != nil {
140
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(internalError)))
141
w.WriteHeader(http.StatusInternalServerError)
142
w.Write(internalError)
144
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(content)))
145
w.WriteHeader(status)
150
// ServeHTTP serves V3UserPass for testing purposes.
151
func (u *V3UserPass) ServeHTTP(w http.ResponseWriter, r *http.Request) {
152
var req V3UserPassRequest
153
// Testing against Canonistack, all responses are application/json, even failures
154
w.Header().Set("Content-Type", "application/json")
155
if r.Header.Get("Content-Type") != "application/json" {
156
u.ReturnFailure(w, http.StatusBadRequest, notJSON)
159
if content, err := ioutil.ReadAll(r.Body); err != nil {
160
w.WriteHeader(http.StatusBadRequest)
163
if err := json.Unmarshal(content, &req); err != nil {
164
u.ReturnFailure(w, http.StatusBadRequest, notJSON)
168
userInfo, errmsg := u.authenticate(
169
req.Auth.Identity.Password.User.Name,
170
req.Auth.Identity.Password.User.Password,
173
u.ReturnFailure(w, http.StatusUnauthorized, errmsg)
177
res, err := u.generateV3TokenResponse(userInfo)
179
u.ReturnFailure(w, http.StatusInternalServerError, err.Error())
182
if req.Auth.Scope.Project.Name != "" {
183
res.Project = &V3Project{
184
ID: u.addTenant(req.Auth.Scope.Project.Name),
187
content, err := json.Marshal(struct {
188
Token *V3TokenResponse `json:"token"`
193
u.ReturnFailure(w, http.StatusInternalServerError, err.Error())
196
w.Header().Set("X-Subject-Token", userInfo.Token)
197
w.WriteHeader(http.StatusCreated)
201
func (u *V3UserPass) generateV3TokenResponse(userInfo *UserInfo) (*V3TokenResponse, error) {
202
res := V3TokenResponse{}
204
res.Issued = time.Now()
205
res.Expires = res.Issued.Add(24 * time.Hour)
206
res.Methods = []string{"password"}
207
res.Catalog = u.services
208
res.User.ID = userInfo.Id
213
// SetupHTTP attaches all the needed handlers to provide the HTTP API.
214
func (u *V3UserPass) SetupHTTP(mux *http.ServeMux) {
215
mux.Handle("/v3/auth/tokens", u)