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  }