github.com/mmatczuk/gohan@v0.0.0-20170206152520-30e45d9bdb69/server/middleware/fake.go (about) 1 // Copyright (C) 2015 NTT Innovation Institute, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package middleware 17 18 import ( 19 "encoding/json" 20 "fmt" 21 "net/http" 22 "strconv" 23 "time" 24 25 "github.com/cloudwan/gohan/schema" 26 "github.com/cloudwan/gohan/util" 27 "github.com/go-martini/martini" 28 "github.com/rackspace/gophercloud" 29 ) 30 31 type tenant struct { 32 ID string `json:"id"` 33 Name string `json:"name"` 34 Description string `json:"description"` 35 Enabled bool `json:"enabled"` 36 } 37 38 type token struct { 39 ID string `json:"id"` 40 ExpiresAt time.Time `json:"expires"` 41 Tenant tenant `json:"tenant"` 42 } 43 44 type role struct { 45 ID string `json:"id"` 46 Name string `json:"name"` 47 } 48 49 var allTenants = []tenant{ 50 tenant{ 51 ID: "fc394f2ab2df4114bde39905f800dc57", 52 Name: "demo", 53 Description: "Demo tenant", 54 Enabled: true, 55 }, 56 tenant{ 57 ID: "acf5662bbff44060b93ac3db3c25a590", 58 Name: "other", 59 Description: "Other tenant", 60 Enabled: true, 61 }, 62 } 63 64 func getToken(id string, t tenant) token { 65 return token{ 66 ID: id, 67 ExpiresAt: time.Now().Add(24 * time.Hour).In(time.UTC), 68 Tenant: t, 69 } 70 } 71 72 var serviceCatalog = []interface{}{ 73 map[string]interface{}{ 74 "type": "gohan", 75 "name": "Gohan", 76 "endpoints": []interface{}{ 77 map[string]interface{}{ 78 "adminURL": "http://127.0.0.1:9091", 79 "internalURL": "http://127.0.0.1:9091", 80 "publicURL": "http://127.0.0.1:9091", 81 "region": "RegionOne", 82 "id": "2dad48f09e2a447a9bf852bcd93548ef", 83 }, 84 }, 85 }, 86 } 87 88 var fakeTokens = map[string]interface{}{ 89 "admin_token": map[string]interface{}{ 90 "access": map[string]interface{}{ 91 "token": getToken("admin_token", allTenants[0]), 92 "serviceCatalog": serviceCatalog, 93 "user": map[string]interface{}{ 94 "id": "admin", 95 "name": "admin", 96 "roles": []role{ 97 role{ 98 Name: "admin", 99 }, 100 }, 101 "roles_links": map[string]interface{}{}, 102 "username": "admin", 103 }, 104 }, 105 }, 106 "demo_token": map[string]interface{}{ 107 "access": map[string]interface{}{ 108 "token": getToken("demo_token", allTenants[0]), 109 "serviceCatalog": serviceCatalog, 110 "user": map[string]interface{}{ 111 "id": "demo", 112 "name": "demo", 113 "roles": []role{ 114 role{ 115 Name: "Member", 116 }, 117 }, 118 "roles_links": map[string]interface{}{}, 119 "username": "demo", 120 }, 121 }, 122 }, 123 "power_user_token": map[string]interface{}{ 124 "access": map[string]interface{}{ 125 "token": getToken("power_user_token", allTenants[1]), 126 "serviceCatalog": serviceCatalog, 127 "user": map[string]interface{}{ 128 "id": "power_user", 129 "name": "power_user", 130 "roles": []role{ 131 role{ 132 Name: "Member", 133 }, 134 }, 135 "roles_links": map[string]interface{}{}, 136 "username": "power_user", 137 }, 138 }, 139 }, 140 } 141 142 //ReadJSON reads JSON from http request 143 func ReadJSON(r *http.Request) (map[string]interface{}, error) { 144 var data interface{} 145 decoder := json.NewDecoder(r.Body) 146 err := decoder.Decode(&data) 147 if err != nil { 148 return nil, err 149 } 150 if _, ok := data.(map[string]interface{}); !ok { 151 return nil, fmt.Errorf("request body is not a data dictionary") 152 } 153 return data.(map[string]interface{}), nil 154 } 155 156 //FakeIdentity middleware 157 type FakeIdentity struct{} 158 159 //VerifyToken fake verify 160 func (*FakeIdentity) VerifyToken(tokenID string) (schema.Authorization, error) { 161 rawToken, ok := fakeTokens[tokenID] 162 if !ok { 163 return nil, fmt.Errorf("authentication error") 164 } 165 166 access, _ := rawToken.(map[string]interface{})["access"].(map[string]interface{}) 167 tenantID := access["token"].(token).Tenant.ID 168 tenantName := access["token"].(token).Tenant.Name 169 role := access["user"].(map[string]interface{})["roles"].([]role)[0].Name 170 171 return schema.NewAuthorization(tenantID, tenantName, tokenID, []string{role}, nil), nil 172 } 173 174 // GetTenantID maps the given tenant name to the tenant's ID 175 func (*FakeIdentity) GetTenantID(tenantName string) (string, error) { 176 for _, tenant := range allTenants { 177 if tenant.Name == tenantName { 178 return tenant.ID, nil 179 } 180 } 181 182 return "", nil 183 } 184 185 // GetTenantName maps the given tenant ID to the tenant's name 186 func (*FakeIdentity) GetTenantName(tenantID string) (string, error) { 187 for _, tenant := range allTenants { 188 if tenant.ID == tenantID { 189 return tenant.Name, nil 190 } 191 } 192 193 return "", nil 194 } 195 196 // GetServiceAuthorization returns the master authorization with full permission 197 func (identity *FakeIdentity) GetServiceAuthorization() (schema.Authorization, error) { 198 return identity.VerifyToken("admin_token") 199 } 200 201 //FakeKeystone server for only test purpose 202 func FakeKeystone(martini *martini.ClassicMartini) { 203 //mocking keystone v2.0 API 204 martini.Post("/v2.0/tokens", func(w http.ResponseWriter, r *http.Request) { 205 authRequest, err := ReadJSON(r) 206 if err != nil { 207 http.Error(w, "", http.StatusBadRequest) 208 } 209 var tokenKey string 210 username, err := util.GetByJSONPointer(authRequest, "/auth/passwordCredentials/username") 211 if err == nil { 212 tokenKey = fmt.Sprintf("%v_token", username) 213 } else { 214 username, err = util.GetByJSONPointer(authRequest, "/auth/token/id") 215 tokenKey = fmt.Sprintf("%v", username) 216 if err != nil { 217 http.Error(w, "", http.StatusBadRequest) 218 } 219 } 220 221 token, ok := fakeTokens[tokenKey] 222 if !ok { 223 http.Error(w, "", http.StatusUnauthorized) 224 } 225 226 serializedToken, _ := json.Marshal(token) 227 w.Header().Set("Content-Type", "application/json") 228 w.Header().Set("Content-Length", strconv.Itoa(len(serializedToken))) 229 w.Write(serializedToken) 230 }) 231 232 martini.Get("/v2.0/tenants", func(w http.ResponseWriter, r *http.Request) { 233 tenants := map[string]interface{}{ 234 "tenants": allTenants, 235 } 236 237 serializedToken, _ := json.Marshal(tenants) 238 w.Header().Set("Content-Type", "application/json") 239 w.Header().Set("Content-Length", strconv.Itoa(len(serializedToken))) 240 w.Write(serializedToken) 241 }) 242 243 for tokenID, rawToken := range fakeTokens { 244 serializedToken, _ := json.Marshal(rawToken) 245 martini.Get("/v2.0/tokens/"+tokenID, func(w http.ResponseWriter, r *http.Request) { 246 w.Write(serializedToken) 247 }) 248 } 249 } 250 251 // GetClient returns openstack client 252 func (identity *FakeIdentity) GetClient() *gophercloud.ServiceClient { 253 return nil 254 }