github.com/dbernstein1/tyk@v2.9.0-beta9-dl-apic+incompatible/gateway/api.go (about)

     1  // Tyk Gateway API
     2  //
     3  // The code below describes the Tyk Gateway API
     4  // Version: 2.8.0
     5  //
     6  //     Schemes: https, http
     7  //     Host: localhost
     8  //     BasePath: /tyk/
     9  //
    10  //     Consumes:
    11  //     - application/json
    12  //
    13  //     Produces:
    14  //     - application/json
    15  //
    16  //     Security:
    17  //     - api_key:
    18  //
    19  //     SecurityDefinitions:
    20  //     api_key:
    21  //          type: apiKey
    22  //          name: X-Tyk-Authorization
    23  //          in: header
    24  //
    25  // swagger:meta
    26  package gateway
    27  
    28  import (
    29  	"bytes"
    30  	"context"
    31  	"encoding/base64"
    32  	"encoding/json"
    33  	"errors"
    34  	"io/ioutil"
    35  	"net/http"
    36  	"net/url"
    37  	"os"
    38  	"path/filepath"
    39  	"strconv"
    40  	"strings"
    41  	"sync"
    42  	"syscall"
    43  	"time"
    44  
    45  	"github.com/gorilla/mux"
    46  	uuid "github.com/satori/go.uuid"
    47  	"github.com/sirupsen/logrus"
    48  	"golang.org/x/crypto/bcrypt"
    49  
    50  	"github.com/TykTechnologies/tyk/apidef"
    51  	"github.com/TykTechnologies/tyk/config"
    52  	"github.com/TykTechnologies/tyk/ctx"
    53  	"github.com/TykTechnologies/tyk/headers"
    54  	"github.com/TykTechnologies/tyk/storage"
    55  	"github.com/TykTechnologies/tyk/user"
    56  )
    57  
    58  // apiModifyKeySuccess represents when a Key modification was successful
    59  //
    60  // swagger:model apiModifyKeySuccess
    61  type apiModifyKeySuccess struct {
    62  	// in:body
    63  	Key     string `json:"key"`
    64  	Status  string `json:"status"`
    65  	Action  string `json:"action"`
    66  	KeyHash string `json:"key_hash,omitempty"`
    67  }
    68  
    69  // apiStatusMessage represents an API status message
    70  //
    71  // swagger:model apiStatusMessage
    72  type apiStatusMessage struct {
    73  	Status string `json:"status"`
    74  	// Response details
    75  	Message string `json:"message"`
    76  }
    77  
    78  func apiOk(msg string) apiStatusMessage {
    79  	return apiStatusMessage{"ok", msg}
    80  }
    81  
    82  func apiError(msg string) apiStatusMessage {
    83  	return apiStatusMessage{"error", msg}
    84  }
    85  
    86  // paginationStatus provides more information about a paginated data set
    87  type paginationStatus struct {
    88  	PageNum   int `json:"page_num"`
    89  	PageTotal int `json:"page_total"`
    90  	PageSize  int `json:"page_size"`
    91  }
    92  
    93  type paginatedOAuthClientTokens struct {
    94  	Pagination paginationStatus
    95  	Tokens     []OAuthClientToken
    96  }
    97  
    98  func doJSONWrite(w http.ResponseWriter, code int, obj interface{}) {
    99  	w.Header().Set(headers.ContentType, headers.ApplicationJSON)
   100  	w.WriteHeader(code)
   101  	if err := json.NewEncoder(w).Encode(obj); err != nil {
   102  		http.Error(w, err.Error(), http.StatusInternalServerError)
   103  	}
   104  	if code != http.StatusOK {
   105  		job := instrument.NewJob("SystemAPIError")
   106  		job.Event(strconv.Itoa(code))
   107  	}
   108  }
   109  
   110  type MethodNotAllowedHandler struct{}
   111  
   112  func (m MethodNotAllowedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   113  	doJSONWrite(w, http.StatusMethodNotAllowed, apiError("Method not supported"))
   114  }
   115  
   116  func addSecureAndCacheHeaders(next http.HandlerFunc) http.HandlerFunc {
   117  	return func(w http.ResponseWriter, r *http.Request) {
   118  		// Setting OWASP Secure Headers
   119  		w.Header().Set("X-Content-Type-Options", "nosniff")
   120  		w.Header().Set("X-XSS-Protection", "1; mode=block")
   121  		w.Header().Set("X-Frame-Options", "DENY")
   122  		w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
   123  
   124  		// Avoid Caching of tokens
   125  		w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
   126  		w.Header().Set("Pragma", "no-cache")
   127  		w.Header().Set("Expires", "0")
   128  		next(w, r)
   129  	}
   130  }
   131  
   132  func allowMethods(next http.HandlerFunc, methods ...string) http.HandlerFunc {
   133  	return func(w http.ResponseWriter, r *http.Request) {
   134  		for _, method := range methods {
   135  			if r.Method == method {
   136  				next(w, r)
   137  				return
   138  			}
   139  		}
   140  		doJSONWrite(w, http.StatusMethodNotAllowed, apiError("Method not supported"))
   141  	}
   142  }
   143  
   144  func getSpecForOrg(orgID string) *APISpec {
   145  	apisMu.RLock()
   146  	defer apisMu.RUnlock()
   147  	for _, v := range apisByID {
   148  		if v.OrgID == orgID {
   149  			return v
   150  		}
   151  	}
   152  
   153  	// If we can't find a spec, it doesn't matter, because we default to Redis anyway, grab whatever you can find
   154  	for _, v := range apisByID {
   155  		return v
   156  	}
   157  	return nil
   158  }
   159  
   160  func checkAndApplyTrialPeriod(keyName, apiId string, newSession *user.SessionState, isHashed bool) {
   161  	// Check the policies to see if we are forcing an expiry on the key
   162  	for _, polID := range newSession.PolicyIDs() {
   163  		policiesMu.RLock()
   164  		policy, ok := policiesByID[polID]
   165  		policiesMu.RUnlock()
   166  		if !ok {
   167  			continue
   168  		}
   169  		// Are we foring an expiry?
   170  		if policy.KeyExpiresIn > 0 {
   171  			// We are, does the key exist?
   172  			_, found := getKeyDetail(keyName, apiId, isHashed)
   173  			if !found {
   174  				// this is a new key, lets expire it
   175  				newSession.Expires = time.Now().Unix() + policy.KeyExpiresIn
   176  			}
   177  		}
   178  	}
   179  }
   180  
   181  func applyPoliciesAndSave(keyName string, session *user.SessionState, spec *APISpec, isHashed bool) error {
   182  	// use basic middleware to apply policies to key/session (it also saves it)
   183  	mw := BaseMiddleware{
   184  		Spec: spec,
   185  	}
   186  	if err := mw.ApplyPolicies(session); err != nil {
   187  		return err
   188  	}
   189  
   190  	lifetime := session.Lifetime(spec.SessionLifetime)
   191  	if err := spec.SessionManager.UpdateSession(keyName, session, lifetime, isHashed); err != nil {
   192  		return err
   193  	}
   194  
   195  	return nil
   196  }
   197  
   198  func resetAPILimits(accessRights map[string]user.AccessDefinition) {
   199  	for apiID := range accessRights {
   200  		// reset API-level limit to nil if it has a zero-value
   201  		if access := accessRights[apiID]; access.Limit != nil && *access.Limit == (user.APILimit{}) {
   202  			access.Limit = nil
   203  			accessRights[apiID] = access
   204  		}
   205  	}
   206  }
   207  
   208  func doAddOrUpdate(keyName string, newSession *user.SessionState, dontReset bool, isHashed bool) error {
   209  	// field last_updated plays an important role in in-mem rate limiter
   210  	// so update last_updated to current timestamp only if suppress_reset wasn't set to 1
   211  	if !dontReset {
   212  		newSession.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
   213  	}
   214  
   215  	if len(newSession.AccessRights) > 0 {
   216  		// reset API-level limit to nil if any has a zero-value
   217  		resetAPILimits(newSession.AccessRights)
   218  		// We have a specific list of access rules, only add / update those
   219  		for apiId := range newSession.AccessRights {
   220  			apiSpec := getApiSpec(apiId)
   221  			if apiSpec == nil {
   222  				log.WithFields(logrus.Fields{
   223  					"prefix":      "api",
   224  					"key":         keyName,
   225  					"org_id":      newSession.OrgID,
   226  					"api_id":      apiId,
   227  					"user_id":     "system",
   228  					"user_ip":     "--",
   229  					"path":        "--",
   230  					"server_name": "system",
   231  				}).Error("Could not add key for this API ID, API doesn't exist.")
   232  				return errors.New("API must be active to add keys")
   233  			}
   234  			checkAndApplyTrialPeriod(keyName, apiId, newSession, isHashed)
   235  
   236  			// Lets reset keys if they are edited by admin
   237  			if !apiSpec.DontSetQuotasOnCreate {
   238  				// Reset quote by default
   239  				if !dontReset {
   240  					apiSpec.SessionManager.ResetQuota(keyName, newSession, isHashed)
   241  					newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
   242  				}
   243  
   244  				// apply polices (if any) and save key
   245  				if err := applyPoliciesAndSave(keyName, newSession, apiSpec, isHashed); err != nil {
   246  					return err
   247  				}
   248  			}
   249  		}
   250  	} else {
   251  		// nothing defined, add key to ALL
   252  		if !config.Global().AllowMasterKeys {
   253  			log.Error("Master keys disallowed in configuration, key not added.")
   254  			return errors.New("Master keys not allowed")
   255  		}
   256  		log.Warning("No API Access Rights set, adding key to ALL.")
   257  		apisMu.RLock()
   258  		defer apisMu.RUnlock()
   259  		for _, spec := range apisByID {
   260  			if !dontReset {
   261  				spec.SessionManager.ResetQuota(keyName, newSession, isHashed)
   262  				newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
   263  			}
   264  			checkAndApplyTrialPeriod(keyName, spec.APIID, newSession, isHashed)
   265  
   266  			// apply polices (if any) and save key
   267  			if err := applyPoliciesAndSave(keyName, newSession, spec, isHashed); err != nil {
   268  				return err
   269  			}
   270  		}
   271  	}
   272  
   273  	log.WithFields(logrus.Fields{
   274  		"prefix":      "api",
   275  		"key":         obfuscateKey(keyName),
   276  		"expires":     newSession.Expires,
   277  		"org_id":      newSession.OrgID,
   278  		"api_id":      "--",
   279  		"user_id":     "system",
   280  		"user_ip":     "--",
   281  		"path":        "--",
   282  		"server_name": "system",
   283  	}).Info("Key added or updated.")
   284  	return nil
   285  }
   286  
   287  // ---- TODO: This changes the URL structure of the API completely ----
   288  // ISSUE: If Session stores are stored with API specs, then managing keys will need to be done per store, i.e. add to all stores,
   289  // remove from all stores, update to all stores, stores handle quotas separately though because they are localised! Keys will
   290  // need to be managed by API, but only for GetDetail, GetList, UpdateKey and DeleteKey
   291  
   292  func setSessionPassword(session *user.SessionState) {
   293  	session.BasicAuthData.Hash = user.HashBCrypt
   294  	newPass, err := bcrypt.GenerateFromPassword([]byte(session.BasicAuthData.Password), 10)
   295  	if err != nil {
   296  		log.Error("Could not hash password, setting to plaintext, error was: ", err)
   297  		session.BasicAuthData.Hash = user.HashPlainText
   298  		return
   299  	}
   300  
   301  	session.BasicAuthData.Password = string(newPass)
   302  }
   303  
   304  func getKeyDetail(key, apiID string, hashed bool) (user.SessionState, bool) {
   305  	sessionManager := FallbackKeySesionManager
   306  	if spec := getApiSpec(apiID); spec != nil {
   307  		sessionManager = spec.SessionManager
   308  	}
   309  
   310  	return sessionManager.SessionDetail(key, hashed)
   311  }
   312  
   313  func handleAddOrUpdate(keyName string, r *http.Request, isHashed bool) (interface{}, int) {
   314  	suppressReset := r.URL.Query().Get("suppress_reset") == "1"
   315  
   316  	// decode payload
   317  	newSession := user.SessionState{}
   318  
   319  	contents, _ := ioutil.ReadAll(r.Body)
   320  	r.Body = ioutil.NopCloser(bytes.NewReader(contents))
   321  
   322  	if err := json.Unmarshal(contents, &newSession); err != nil {
   323  		log.Error("Couldn't decode new session object: ", err)
   324  		return apiError("Request malformed"), http.StatusBadRequest
   325  	}
   326  
   327  	mw := BaseMiddleware{}
   328  	mw.ApplyPolicies(&newSession)
   329  
   330  	// DO ADD OR UPDATE
   331  
   332  	// get original session in case of update and preserve fields that SHOULD NOT be updated
   333  	originalKey := user.SessionState{}
   334  	if r.Method == http.MethodPut {
   335  		found := false
   336  		for apiID := range newSession.AccessRights {
   337  			originalKey, found = getKeyDetail(keyName, apiID, isHashed)
   338  			if found {
   339  				break
   340  			}
   341  		}
   342  		if !found {
   343  			log.Error("Could not find key when updating")
   344  			return apiError("Key is not found"), http.StatusNotFound
   345  		}
   346  
   347  		// don't change fields related to quota and rate limiting if was passed as "suppress_reset=1"
   348  		if suppressReset {
   349  			// save existing quota_renews and last_updated if suppress_reset was passed
   350  			// (which means don't reset quota or rate counters)
   351  			// - leaving quota_renews as 0 will force quota limiter to start new renewal period
   352  			// - setting new last_updated with force rate limiter to start new "per" rating period
   353  
   354  			// on session level
   355  			newSession.QuotaRenews = originalKey.QuotaRenews
   356  			newSession.LastUpdated = originalKey.LastUpdated
   357  
   358  			// on ACL API limit level
   359  			for apiID, access := range originalKey.AccessRights {
   360  				if access.Limit == nil {
   361  					continue
   362  				}
   363  				if newAccess, ok := newSession.AccessRights[apiID]; ok && newAccess.Limit != nil {
   364  					newAccess.Limit.QuotaRenews = access.Limit.QuotaRenews
   365  					newSession.AccessRights[apiID] = newAccess
   366  				}
   367  			}
   368  		}
   369  	} else {
   370  		newSession.DateCreated = time.Now()
   371  	}
   372  
   373  	// Update our session object (create it)
   374  	if newSession.BasicAuthData.Password != "" {
   375  		// If we are using a basic auth user, then we need to make the keyname explicit against the OrgId in order to differentiate it
   376  		// Only if it's NEW
   377  		switch r.Method {
   378  		case http.MethodPost:
   379  			keyName = generateToken(newSession.OrgID, keyName)
   380  			// It's a create, so lets hash the password
   381  			setSessionPassword(&newSession)
   382  		case http.MethodPut:
   383  			if originalKey.BasicAuthData.Password != newSession.BasicAuthData.Password {
   384  				// passwords dont match assume it's new, lets hash it
   385  				log.Debug("Passwords dont match, original: ", originalKey.BasicAuthData.Password)
   386  				log.Debug("New: newSession.BasicAuthData.Password")
   387  				log.Debug("Changing password")
   388  				setSessionPassword(&newSession)
   389  			}
   390  		}
   391  	}
   392  
   393  	if err := doAddOrUpdate(keyName, &newSession, suppressReset, isHashed); err != nil {
   394  		return apiError("Failed to create key, ensure security settings are correct."), http.StatusInternalServerError
   395  	}
   396  
   397  	action := "modified"
   398  	event := EventTokenUpdated
   399  	if r.Method == http.MethodPost {
   400  		action = "added"
   401  		event = EventTokenCreated
   402  	}
   403  	FireSystemEvent(event, EventTokenMeta{
   404  		EventMetaDefault: EventMetaDefault{Message: "Key modified."},
   405  		Org:              newSession.OrgID,
   406  		Key:              keyName,
   407  	})
   408  
   409  	response := apiModifyKeySuccess{
   410  		Key:    keyName,
   411  		Status: "ok",
   412  		Action: action,
   413  	}
   414  
   415  	// add key hash for newly created key
   416  	if config.Global().HashKeys && r.Method == http.MethodPost {
   417  		if isHashed {
   418  			response.KeyHash = keyName
   419  		} else {
   420  			response.KeyHash = storage.HashKey(keyName)
   421  		}
   422  	}
   423  
   424  	return response, http.StatusOK
   425  }
   426  
   427  func handleGetDetail(sessionKey, apiID string, byHash bool) (interface{}, int) {
   428  	if byHash && !config.Global().HashKeys {
   429  		return apiError("Key requested by hash but key hashing is not enabled"), http.StatusBadRequest
   430  	}
   431  
   432  	sessionManager := FallbackKeySesionManager
   433  	spec := getApiSpec(apiID)
   434  	if spec != nil {
   435  		sessionManager = spec.SessionManager
   436  	}
   437  
   438  	var session user.SessionState
   439  	var ok bool
   440  	session, ok = sessionManager.SessionDetail(sessionKey, byHash)
   441  
   442  	if !ok {
   443  		return apiError("Key not found"), http.StatusNotFound
   444  	}
   445  
   446  	quotaKey := QuotaKeyPrefix + storage.HashKey(sessionKey)
   447  	if byHash {
   448  		quotaKey = QuotaKeyPrefix + sessionKey
   449  	}
   450  
   451  	if usedQuota, err := sessionManager.Store().GetRawKey(quotaKey); err == nil {
   452  		qInt, _ := strconv.Atoi(usedQuota)
   453  		remaining := session.QuotaMax - int64(qInt)
   454  
   455  		if remaining < 0 {
   456  			session.QuotaRemaining = 0
   457  		} else {
   458  			session.QuotaRemaining = remaining
   459  		}
   460  	} else {
   461  		log.WithFields(logrus.Fields{
   462  			"prefix":  "api",
   463  			"key":     obfuscateKey(sessionKey),
   464  			"message": err,
   465  			"status":  "ok",
   466  		}).Info("Can't retrieve key quota")
   467  	}
   468  
   469  	// populate remaining quota for API limits (if any)
   470  	for id, access := range session.AccessRights {
   471  		if access.Limit == nil {
   472  			continue
   473  		}
   474  
   475  		limQuotaKey := QuotaKeyPrefix + id + "-" + storage.HashKey(sessionKey)
   476  		if byHash {
   477  			limQuotaKey = QuotaKeyPrefix + id + "-" + sessionKey
   478  		}
   479  		if usedQuota, err := sessionManager.Store().GetRawKey(limQuotaKey); err == nil {
   480  			qInt, _ := strconv.Atoi(usedQuota)
   481  			remaining := access.Limit.QuotaMax - int64(qInt)
   482  
   483  			if remaining < 0 {
   484  				access.Limit.QuotaRemaining = 0
   485  			} else {
   486  				access.Limit.QuotaRemaining = remaining
   487  			}
   488  			session.AccessRights[id] = access
   489  		} else {
   490  			access.Limit.QuotaRemaining = access.Limit.QuotaMax
   491  			session.AccessRights[id] = access
   492  
   493  			log.WithFields(logrus.Fields{
   494  				"prefix": "api",
   495  				"apiID":  id,
   496  				"key":    obfuscateKey(sessionKey),
   497  				"error":  err,
   498  			}).Info("Can't retrieve api limit quota")
   499  		}
   500  	}
   501  
   502  	mw := BaseMiddleware{Spec: spec}
   503  	mw.ApplyPolicies(&session)
   504  
   505  	log.WithFields(logrus.Fields{
   506  		"prefix": "api",
   507  		"key":    obfuscateKey(sessionKey),
   508  		"status": "ok",
   509  	}).Info("Retrieved key detail.")
   510  
   511  	return session, http.StatusOK
   512  }
   513  
   514  // apiAllKeys represents a list of keys in the memory store
   515  // swagger:model
   516  type apiAllKeys struct {
   517  	APIKeys []string `json:"keys"`
   518  }
   519  
   520  func handleGetAllKeys(filter, apiID string) (interface{}, int) {
   521  	sessionManager := FallbackKeySesionManager
   522  	if spec := getApiSpec(apiID); spec != nil {
   523  		sessionManager = spec.SessionManager
   524  	}
   525  
   526  	sessions := sessionManager.Sessions(filter)
   527  
   528  	fixed_sessions := make([]string, 0)
   529  	for _, s := range sessions {
   530  		if !strings.HasPrefix(s, QuotaKeyPrefix) && !strings.HasPrefix(s, RateLimitKeyPrefix) {
   531  			fixed_sessions = append(fixed_sessions, s)
   532  		}
   533  	}
   534  
   535  	sessionsObj := apiAllKeys{fixed_sessions}
   536  
   537  	log.WithFields(logrus.Fields{
   538  		"prefix": "api",
   539  		"status": "ok",
   540  	}).Info("Retrieved key list.")
   541  
   542  	return sessionsObj, http.StatusOK
   543  }
   544  
   545  func handleAddKey(keyName, hashedName, sessionString, apiID string) {
   546  	mw := BaseMiddleware{
   547  		Spec: &APISpec{
   548  			SessionManager: FallbackKeySesionManager,
   549  		},
   550  	}
   551  	sess := user.SessionState{}
   552  	json.Unmarshal([]byte(sessionString), &sess)
   553  	sess.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
   554  	var err error
   555  	if config.Global().HashKeys {
   556  		err = mw.Spec.SessionManager.UpdateSession(hashedName, &sess, 0, true)
   557  	} else {
   558  		err = mw.Spec.SessionManager.UpdateSession(keyName, &sess, 0, false)
   559  	}
   560  	if err != nil {
   561  		log.WithFields(logrus.Fields{
   562  			"prefix": "api",
   563  			"key":    obfuscateKey(keyName),
   564  			"status": "fail",
   565  			"err":    err,
   566  		}).Error("Failed to update key.")
   567  	}
   568  	log.WithFields(logrus.Fields{
   569  		"prefix": "RPC",
   570  		"key":    obfuscateKey(keyName),
   571  		"status": "ok",
   572  	}).Info("Updated hashed key in slave storage.")
   573  }
   574  
   575  func handleDeleteKey(keyName, apiID string, resetQuota bool) (interface{}, int) {
   576  	if apiID == "-1" {
   577  		// Go through ALL managed API's and delete the key
   578  		apisMu.RLock()
   579  		removed := false
   580  		for _, spec := range apisByID {
   581  			if spec.SessionManager.RemoveSession(keyName, false) {
   582  				removed = true
   583  			}
   584  			spec.SessionManager.ResetQuota(keyName, &user.SessionState{}, false)
   585  		}
   586  		apisMu.RUnlock()
   587  
   588  		if !removed {
   589  			log.WithFields(logrus.Fields{
   590  				"prefix": "api",
   591  				"key":    obfuscateKey(keyName),
   592  				"status": "fail",
   593  			}).Error("Failed to remove the key")
   594  			return apiError("Failed to remove the key"), http.StatusBadRequest
   595  		}
   596  
   597  		log.WithFields(logrus.Fields{
   598  			"prefix": "api",
   599  			"key":    keyName,
   600  			"status": "ok",
   601  		}).Info("Deleted key across all APIs.")
   602  
   603  		return nil, http.StatusOK
   604  	}
   605  
   606  	orgID := ""
   607  	sessionManager := FallbackKeySesionManager
   608  	if spec := getApiSpec(apiID); spec != nil {
   609  		orgID = spec.OrgID
   610  		sessionManager = spec.SessionManager
   611  	}
   612  
   613  	if !sessionManager.RemoveSession(keyName, false) {
   614  		log.WithFields(logrus.Fields{
   615  			"prefix": "api",
   616  			"key":    obfuscateKey(keyName),
   617  			"status": "fail",
   618  		}).Error("Failed to remove the key")
   619  		return apiError("Failed to remove the key"), http.StatusBadRequest
   620  	}
   621  
   622  	if resetQuota {
   623  		sessionManager.ResetQuota(keyName, &user.SessionState{}, false)
   624  	}
   625  
   626  	statusObj := apiModifyKeySuccess{
   627  		Key:    keyName,
   628  		Status: "ok",
   629  		Action: "deleted",
   630  	}
   631  
   632  	FireSystemEvent(EventTokenDeleted, EventTokenMeta{
   633  		EventMetaDefault: EventMetaDefault{Message: "Key deleted."},
   634  		Org:              orgID,
   635  		Key:              keyName,
   636  	})
   637  
   638  	log.WithFields(logrus.Fields{
   639  		"prefix": "api",
   640  		"key":    keyName,
   641  		"status": "ok",
   642  	}).Info("Deleted key.")
   643  
   644  	return statusObj, http.StatusOK
   645  }
   646  
   647  func handleDeleteHashedKey(keyName, apiID string, resetQuota bool) (interface{}, int) {
   648  	if apiID == "-1" {
   649  		// Go through ALL managed API's and delete the key
   650  		removed := false
   651  		apisMu.RLock()
   652  		for _, spec := range apisByID {
   653  			if spec.SessionManager.RemoveSession(keyName, true) {
   654  				removed = true
   655  			}
   656  		}
   657  		apisMu.RUnlock()
   658  
   659  		if !removed {
   660  			log.WithFields(logrus.Fields{
   661  				"prefix": "api",
   662  				"key":    obfuscateKey(keyName),
   663  				"status": "fail",
   664  			}).Error("Failed to remove the key")
   665  			return apiError("Failed to remove the key"), http.StatusBadRequest
   666  		}
   667  
   668  		log.WithFields(logrus.Fields{
   669  			"prefix": "api",
   670  			"key":    keyName,
   671  			"status": "ok",
   672  		}).Info("Deleted hashed key across all APIs.")
   673  
   674  		return nil, http.StatusOK
   675  	}
   676  
   677  	sessionManager := FallbackKeySesionManager
   678  	if spec := getApiSpec(apiID); spec != nil {
   679  		sessionManager = spec.SessionManager
   680  	}
   681  
   682  	if !sessionManager.RemoveSession(keyName, true) {
   683  		log.WithFields(logrus.Fields{
   684  			"prefix": "api",
   685  			"key":    obfuscateKey(keyName),
   686  			"status": "fail",
   687  		}).Error("Failed to remove the key")
   688  		return apiError("Failed to remove the key"), http.StatusBadRequest
   689  	}
   690  
   691  	if resetQuota {
   692  		sessionManager.ResetQuota(keyName, &user.SessionState{}, true)
   693  	}
   694  
   695  	statusObj := apiModifyKeySuccess{
   696  		Key:    keyName,
   697  		Status: "ok",
   698  		Action: "deleted",
   699  	}
   700  
   701  	log.WithFields(logrus.Fields{
   702  		"prefix": "api",
   703  		"key":    keyName,
   704  		"status": "ok",
   705  	}).Info("Deleted hashed key.")
   706  
   707  	return statusObj, http.StatusOK
   708  }
   709  
   710  func handleGetAPIList() (interface{}, int) {
   711  	apisMu.RLock()
   712  	defer apisMu.RUnlock()
   713  	apiIDList := make([]*apidef.APIDefinition, len(apisByID))
   714  	c := 0
   715  	for _, apiSpec := range apisByID {
   716  		apiIDList[c] = apiSpec.APIDefinition
   717  		c++
   718  	}
   719  	return apiIDList, http.StatusOK
   720  }
   721  
   722  func handleGetAPI(apiID string) (interface{}, int) {
   723  	if spec := getApiSpec(apiID); spec != nil {
   724  		return spec.APIDefinition, http.StatusOK
   725  	}
   726  
   727  	log.WithFields(logrus.Fields{
   728  		"prefix": "api",
   729  		"apiID":  apiID,
   730  	}).Error("API doesn't exist.")
   731  	return apiError("API not found"), http.StatusNotFound
   732  }
   733  
   734  func handleAddOrUpdateApi(apiID string, r *http.Request) (interface{}, int) {
   735  	if config.Global().UseDBAppConfigs {
   736  		log.Error("Rejected new API Definition due to UseDBAppConfigs = true")
   737  		return apiError("Due to enabled use_db_app_configs, please use the Dashboard API"), http.StatusInternalServerError
   738  	}
   739  
   740  	newDef := &apidef.APIDefinition{}
   741  	if err := json.NewDecoder(r.Body).Decode(newDef); err != nil {
   742  		log.Error("Couldn't decode new API Definition object: ", err)
   743  		return apiError("Request malformed"), http.StatusBadRequest
   744  	}
   745  
   746  	if apiID != "" && newDef.APIID != apiID {
   747  		log.Error("PUT operation on different APIIDs")
   748  		return apiError("Request APIID does not match that in Definition! For Updtae operations these must match."), http.StatusBadRequest
   749  	}
   750  
   751  	// Create a filename
   752  	defFilePath := filepath.Join(config.Global().AppPath, newDef.APIID+".json")
   753  
   754  	// If it exists, delete it
   755  	if _, err := os.Stat(defFilePath); err == nil {
   756  		log.Warning("API Definition with this ID already exists, deleting file...")
   757  		os.Remove(defFilePath)
   758  	}
   759  
   760  	// unmarshal the object into the file
   761  	asByte, err := json.MarshalIndent(newDef, "", "  ")
   762  	if err != nil {
   763  		log.Error("Marshalling of API Definition failed: ", err)
   764  		return apiError("Marshalling failed"), http.StatusInternalServerError
   765  	}
   766  
   767  	if err := ioutil.WriteFile(defFilePath, asByte, 0644); err != nil {
   768  		log.Error("Failed to create file! - ", err)
   769  		return apiError("File object creation failed, write error"), http.StatusInternalServerError
   770  	}
   771  
   772  	action := "modified"
   773  	if r.Method == "POST" {
   774  		action = "added"
   775  	}
   776  
   777  	response := apiModifyKeySuccess{
   778  		Key:    newDef.APIID,
   779  		Status: "ok",
   780  		Action: action,
   781  	}
   782  
   783  	return response, http.StatusOK
   784  }
   785  
   786  func handleDeleteAPI(apiID string) (interface{}, int) {
   787  	// Generate a filename
   788  	defFilePath := filepath.Join(config.Global().AppPath, apiID+".json")
   789  
   790  	// If it exists, delete it
   791  	if _, err := os.Stat(defFilePath); err != nil {
   792  		log.Warning("File does not exist! ", err)
   793  		return apiError("Delete failed"), http.StatusInternalServerError
   794  	}
   795  
   796  	os.Remove(defFilePath)
   797  
   798  	response := apiModifyKeySuccess{
   799  		Key:    apiID,
   800  		Status: "ok",
   801  		Action: "deleted",
   802  	}
   803  
   804  	return response, http.StatusOK
   805  }
   806  
   807  func apiHandler(w http.ResponseWriter, r *http.Request) {
   808  	apiID := mux.Vars(r)["apiID"]
   809  
   810  	var obj interface{}
   811  	var code int
   812  
   813  	switch r.Method {
   814  	case "GET":
   815  		if apiID != "" {
   816  			log.Debug("Requesting API definition for", apiID)
   817  			obj, code = handleGetAPI(apiID)
   818  		} else {
   819  			log.Debug("Requesting API list")
   820  			obj, code = handleGetAPIList()
   821  		}
   822  	case "POST":
   823  		log.Debug("Creating new definition file")
   824  		obj, code = handleAddOrUpdateApi(apiID, r)
   825  	case "PUT":
   826  		if apiID != "" {
   827  			log.Debug("Updating existing API: ", apiID)
   828  			obj, code = handleAddOrUpdateApi(apiID, r)
   829  		} else {
   830  			obj, code = apiError("Must specify an apiID to update"), http.StatusBadRequest
   831  		}
   832  	case "DELETE":
   833  		if apiID != "" {
   834  			log.Debug("Deleting API definition for: ", apiID)
   835  			obj, code = handleDeleteAPI(apiID)
   836  		} else {
   837  			obj, code = apiError("Must specify an apiID to delete"), http.StatusBadRequest
   838  		}
   839  	}
   840  
   841  	doJSONWrite(w, code, obj)
   842  }
   843  
   844  func keyHandler(w http.ResponseWriter, r *http.Request) {
   845  	keyName := mux.Vars(r)["keyName"]
   846  	apiID := r.URL.Query().Get("api_id")
   847  	isHashed := r.URL.Query().Get("hashed") != ""
   848  	isUserName := r.URL.Query().Get("username") == "true"
   849  	orgID := r.URL.Query().Get("org_id")
   850  
   851  	// check if passed key is user name and convert it to real key with respect to current hashing algorithm
   852  	origKeyName := keyName
   853  	if r.Method != http.MethodPost && isUserName {
   854  		keyName = generateToken(orgID, keyName)
   855  	}
   856  
   857  	var obj interface{}
   858  	var code int
   859  	hashKeyFunction := config.Global().HashKeyFunction
   860  
   861  	switch r.Method {
   862  	case http.MethodPost:
   863  		obj, code = handleAddOrUpdate(keyName, r, isHashed)
   864  	case http.MethodPut:
   865  		obj, code = handleAddOrUpdate(keyName, r, isHashed)
   866  		if code != http.StatusOK && hashKeyFunction != "" {
   867  			// try to use legacy key format
   868  			obj, code = handleAddOrUpdate(origKeyName, r, isHashed)
   869  		}
   870  	case http.MethodGet:
   871  		if keyName != "" {
   872  			// Return single key detail
   873  			obj, code = handleGetDetail(keyName, apiID, isHashed)
   874  			if code != http.StatusOK && hashKeyFunction != "" {
   875  				// try to use legacy key format
   876  				obj, code = handleGetDetail(origKeyName, apiID, isHashed)
   877  			}
   878  		} else {
   879  			// Return list of keys
   880  			if config.Global().HashKeys {
   881  				// get all keys is disabled by default
   882  				if !config.Global().EnableHashedKeysListing {
   883  					doJSONWrite(
   884  						w,
   885  						http.StatusNotFound,
   886  						apiError("Hashed key listing is disabled in config (enable_hashed_keys_listing)"),
   887  					)
   888  					return
   889  				}
   890  
   891  				// we don't use filter for hashed keys
   892  				obj, code = handleGetAllKeys("", apiID)
   893  			} else {
   894  				filter := r.URL.Query().Get("filter")
   895  				obj, code = handleGetAllKeys(filter, apiID)
   896  			}
   897  		}
   898  
   899  	case http.MethodDelete:
   900  		// Remove a key
   901  		if !isHashed {
   902  			obj, code = handleDeleteKey(keyName, apiID, true)
   903  		} else {
   904  			obj, code = handleDeleteHashedKey(keyName, apiID, true)
   905  		}
   906  		if code != http.StatusOK && hashKeyFunction != "" {
   907  			// try to use legacy key format
   908  			if !isHashed {
   909  				obj, code = handleDeleteKey(origKeyName, apiID, true)
   910  			} else {
   911  				obj, code = handleDeleteHashedKey(origKeyName, apiID, true)
   912  			}
   913  		}
   914  	}
   915  
   916  	doJSONWrite(w, code, obj)
   917  }
   918  
   919  type PolicyUpdateObj struct {
   920  	Policy string `json:"policy"`
   921  }
   922  
   923  func policyUpdateHandler(w http.ResponseWriter, r *http.Request) {
   924  	log.Warning("Hashed key change request detected!")
   925  
   926  	var policRecord PolicyUpdateObj
   927  	if err := json.NewDecoder(r.Body).Decode(&policRecord); err != nil {
   928  		doJSONWrite(w, http.StatusBadRequest, apiError("Couldn't decode instruction"))
   929  		return
   930  	}
   931  
   932  	keyName := mux.Vars(r)["keyName"]
   933  	apiID := r.URL.Query().Get("api_id")
   934  	obj, code := handleUpdateHashedKey(keyName, apiID, policRecord.Policy)
   935  
   936  	doJSONWrite(w, code, obj)
   937  }
   938  
   939  func handleUpdateHashedKey(keyName, apiID, policyId string) (interface{}, int) {
   940  	sessionManager := FallbackKeySesionManager
   941  	if spec := getApiSpec(apiID); spec != nil {
   942  		sessionManager = spec.SessionManager
   943  	}
   944  
   945  	sess, ok := sessionManager.SessionDetail(keyName, true)
   946  	if !ok {
   947  		log.WithFields(logrus.Fields{
   948  			"prefix": "api",
   949  			"key":    keyName,
   950  			"status": "fail",
   951  		}).Error("Failed to update hashed key.")
   952  
   953  		return apiError("Key not found"), http.StatusNotFound
   954  	}
   955  
   956  	// Set the policy
   957  	sess.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
   958  	sess.SetPolicies(policyId)
   959  
   960  	err := sessionManager.UpdateSession(keyName, &sess, 0, true)
   961  	if err != nil {
   962  		log.WithFields(logrus.Fields{
   963  			"prefix": "api",
   964  			"key":    keyName,
   965  			"status": "fail",
   966  			"err":    err,
   967  		}).Error("Failed to update hashed key.")
   968  
   969  		return apiError("Could not write key data"), http.StatusInternalServerError
   970  	}
   971  
   972  	statusObj := apiModifyKeySuccess{
   973  		Key:    keyName,
   974  		Status: "ok",
   975  		Action: "updated",
   976  	}
   977  
   978  	log.WithFields(logrus.Fields{
   979  		"prefix": "api",
   980  		"key":    keyName,
   981  		"status": "ok",
   982  	}).Info("Updated hashed key.")
   983  
   984  	return statusObj, http.StatusOK
   985  }
   986  
   987  func orgHandler(w http.ResponseWriter, r *http.Request) {
   988  	keyName := mux.Vars(r)["keyName"]
   989  	filter := r.URL.Query().Get("filter")
   990  	var obj interface{}
   991  	var code int
   992  
   993  	switch r.Method {
   994  	case "POST", "PUT":
   995  		obj, code = handleOrgAddOrUpdate(keyName, r)
   996  
   997  	case "GET":
   998  		if keyName != "" {
   999  			// Return single org detail
  1000  			obj, code = handleGetOrgDetail(keyName)
  1001  		} else {
  1002  			// Return list of keys
  1003  			obj, code = handleGetAllOrgKeys(filter)
  1004  		}
  1005  
  1006  	case "DELETE":
  1007  		// Remove a key
  1008  		obj, code = handleDeleteOrgKey(keyName)
  1009  	}
  1010  
  1011  	doJSONWrite(w, code, obj)
  1012  }
  1013  
  1014  func handleOrgAddOrUpdate(keyName string, r *http.Request) (interface{}, int) {
  1015  	newSession := new(user.SessionState)
  1016  
  1017  	if err := json.NewDecoder(r.Body).Decode(newSession); err != nil {
  1018  		log.Error("Couldn't decode new session object: ", err)
  1019  		return apiError("Request malformed"), http.StatusBadRequest
  1020  	}
  1021  	// Update our session object (create it)
  1022  
  1023  	spec := getSpecForOrg(keyName)
  1024  	var sessionManager SessionHandler
  1025  
  1026  	if spec == nil {
  1027  		log.Warning("Couldn't find org session store in active API list")
  1028  		if config.Global().SupressDefaultOrgStore {
  1029  			return apiError("No such organisation found in Active API list"), http.StatusNotFound
  1030  		}
  1031  		sessionManager = &DefaultOrgStore
  1032  	} else {
  1033  		sessionManager = spec.OrgSessionManager
  1034  	}
  1035  
  1036  	if r.URL.Query().Get("reset_quota") == "1" {
  1037  		sessionManager.ResetQuota(keyName, newSession, false)
  1038  		newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
  1039  		rawKey := QuotaKeyPrefix + storage.HashKey(keyName)
  1040  
  1041  		// manage quotas separately
  1042  		DefaultQuotaStore.RemoveSession(rawKey, false)
  1043  	}
  1044  
  1045  	err := sessionManager.UpdateSession(keyName, newSession, 0, false)
  1046  	if err != nil {
  1047  		return apiError("Error writing to key store " + err.Error()), http.StatusInternalServerError
  1048  	}
  1049  
  1050  	// identify that spec has org session
  1051  	if spec != nil {
  1052  		spec.Lock()
  1053  		spec.OrgHasNoSession = false
  1054  		spec.Unlock()
  1055  	}
  1056  
  1057  	log.WithFields(logrus.Fields{
  1058  		"prefix": "api",
  1059  		"org":    keyName,
  1060  		"status": "ok",
  1061  	}).Info("New organization key added or updated.")
  1062  
  1063  	action := "modified"
  1064  	if r.Method == "POST" {
  1065  		action = "added"
  1066  	}
  1067  
  1068  	response := apiModifyKeySuccess{
  1069  		Key:    keyName,
  1070  		Status: "ok",
  1071  		Action: action,
  1072  	}
  1073  
  1074  	return response, http.StatusOK
  1075  }
  1076  
  1077  func handleGetOrgDetail(orgID string) (interface{}, int) {
  1078  	spec := getSpecForOrg(orgID)
  1079  	if spec == nil {
  1080  		return apiError("Org not found"), http.StatusNotFound
  1081  	}
  1082  
  1083  	session, ok := spec.OrgSessionManager.SessionDetail(orgID, false)
  1084  	if !ok {
  1085  		log.WithFields(logrus.Fields{
  1086  			"prefix": "api",
  1087  			"org":    orgID,
  1088  			"status": "fail",
  1089  			"err":    "not found",
  1090  		}).Error("Failed retrieval of record for ORG ID.")
  1091  		return apiError("Org not found"), http.StatusNotFound
  1092  	}
  1093  	log.WithFields(logrus.Fields{
  1094  		"prefix": "api",
  1095  		"org":    orgID,
  1096  		"status": "ok",
  1097  	}).Info("Retrieved record for ORG ID.")
  1098  	return session, http.StatusOK
  1099  }
  1100  
  1101  func handleGetAllOrgKeys(filter string) (interface{}, int) {
  1102  	spec := getSpecForOrg("")
  1103  	if spec == nil {
  1104  		return apiError("ORG not found"), http.StatusNotFound
  1105  	}
  1106  
  1107  	sessions := spec.OrgSessionManager.Sessions(filter)
  1108  	fixed_sessions := make([]string, 0)
  1109  	for _, s := range sessions {
  1110  		if !strings.HasPrefix(s, QuotaKeyPrefix) && !strings.HasPrefix(s, RateLimitKeyPrefix) {
  1111  			fixed_sessions = append(fixed_sessions, s)
  1112  		}
  1113  	}
  1114  	sessionsObj := apiAllKeys{fixed_sessions}
  1115  	return sessionsObj, http.StatusOK
  1116  }
  1117  
  1118  func handleDeleteOrgKey(orgID string) (interface{}, int) {
  1119  	spec := getSpecForOrg(orgID)
  1120  	if spec == nil {
  1121  		log.WithFields(logrus.Fields{
  1122  			"prefix": "api",
  1123  			"key":    orgID,
  1124  			"status": "fail",
  1125  			"err":    "not found",
  1126  		}).Error("Failed to delete org key.")
  1127  
  1128  		return apiError("Org not found"), http.StatusNotFound
  1129  	}
  1130  
  1131  	if !spec.OrgSessionManager.RemoveSession(orgID, false) {
  1132  		return apiError("Failed to remove the key"), http.StatusBadRequest
  1133  	}
  1134  
  1135  	log.WithFields(logrus.Fields{
  1136  		"prefix": "api",
  1137  		"key":    orgID,
  1138  		"status": "ok",
  1139  	}).Info("Org key deleted.")
  1140  
  1141  	// identify that spec has no org session
  1142  	if spec != nil {
  1143  		spec.Lock()
  1144  		spec.OrgHasNoSession = true
  1145  		spec.Unlock()
  1146  	}
  1147  
  1148  	statusObj := apiModifyKeySuccess{
  1149  		Key:    orgID,
  1150  		Status: "ok",
  1151  		Action: "deleted",
  1152  	}
  1153  	return statusObj, http.StatusOK
  1154  }
  1155  
  1156  func groupResetHandler(w http.ResponseWriter, r *http.Request) {
  1157  	log.WithFields(logrus.Fields{
  1158  		"prefix": "api",
  1159  		"status": "ok",
  1160  	}).Info("Group reload accepted.")
  1161  
  1162  	// Signal to the group via redis
  1163  	MainNotifier.Notify(Notification{Command: NoticeGroupReload})
  1164  
  1165  	log.WithFields(logrus.Fields{
  1166  		"prefix": "api",
  1167  	}).Info("Reloaded URL Structure - Success")
  1168  
  1169  	doJSONWrite(w, http.StatusOK, apiOk(""))
  1170  }
  1171  
  1172  // resetHandler will try to queue a reload. If fn is nil and block=true
  1173  // was in the URL parameters, it will block until the reload is done.
  1174  // Otherwise, it won't block and fn will be called once the reload is
  1175  // finished.
  1176  //
  1177  func resetHandler(fn func()) http.HandlerFunc {
  1178  	return func(w http.ResponseWriter, r *http.Request) {
  1179  		var wg sync.WaitGroup
  1180  
  1181  		if fn == nil && r.URL.Query().Get("block") == "true" {
  1182  			wg.Add(1)
  1183  			reloadURLStructure(wg.Done)
  1184  		} else {
  1185  			reloadURLStructure(fn)
  1186  		}
  1187  
  1188  		log.WithFields(logrus.Fields{
  1189  			"prefix": "api",
  1190  		}).Info("Reload URL Structure - Scheduled")
  1191  
  1192  		wg.Wait()
  1193  		doJSONWrite(w, http.StatusOK, apiOk(""))
  1194  	}
  1195  }
  1196  
  1197  func hotReloadHandler(w http.ResponseWriter, r *http.Request) {
  1198  	log.WithFields(logrus.Fields{
  1199  		"prefix": "api",
  1200  	}).Info("Triggering Hot Reload")
  1201  	doJSONWrite(w, http.StatusOK, apiOk(""))
  1202  	if err := syscall.Kill(hostDetails.PID, syscall.SIGUSR2); err != nil {
  1203  		log.Error("Process reload failed: ", err)
  1204  	}
  1205  }
  1206  
  1207  func createKeyHandler(w http.ResponseWriter, r *http.Request) {
  1208  	newSession := new(user.SessionState)
  1209  	if err := json.NewDecoder(r.Body).Decode(newSession); err != nil {
  1210  		log.WithFields(logrus.Fields{
  1211  			"prefix": "api",
  1212  			"status": "fail",
  1213  			"err":    err,
  1214  		}).Error("Key creation failed.")
  1215  		doJSONWrite(w, http.StatusInternalServerError, apiError("Unmarshalling failed"))
  1216  		return
  1217  	}
  1218  
  1219  	newKey := keyGen.GenerateAuthKey(newSession.OrgID)
  1220  	if newSession.HMACEnabled {
  1221  		newSession.HmacSecret = keyGen.GenerateHMACSecret()
  1222  	}
  1223  
  1224  	if newSession.Certificate != "" {
  1225  		newKey = generateToken(newSession.OrgID, newSession.Certificate)
  1226  	}
  1227  
  1228  	newSession.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
  1229  	newSession.DateCreated = time.Now()
  1230  
  1231  	if len(newSession.AccessRights) > 0 {
  1232  		// reset API-level limit to nil if any has a zero-value
  1233  		resetAPILimits(newSession.AccessRights)
  1234  		for apiID := range newSession.AccessRights {
  1235  			apiSpec := getApiSpec(apiID)
  1236  			if apiSpec != nil {
  1237  				checkAndApplyTrialPeriod(newKey, apiID, newSession, false)
  1238  				// If we have enabled HMAC checking for keys, we need to generate a secret for the client to use
  1239  				if !apiSpec.DontSetQuotasOnCreate {
  1240  					// Reset quota by default
  1241  					apiSpec.SessionManager.ResetQuota(newKey, newSession, false)
  1242  					newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
  1243  				}
  1244  				// apply polices (if any) and save key
  1245  				if err := applyPoliciesAndSave(newKey, newSession, apiSpec, false); err != nil {
  1246  					doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error()))
  1247  					return
  1248  				}
  1249  			} else {
  1250  				// Use fallback
  1251  				sessionManager := FallbackKeySesionManager
  1252  				newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
  1253  				sessionManager.ResetQuota(newKey, newSession, false)
  1254  				err := sessionManager.UpdateSession(newKey, newSession, -1, false)
  1255  				if err != nil {
  1256  					doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error()))
  1257  					return
  1258  				}
  1259  			}
  1260  		}
  1261  	} else {
  1262  		if config.Global().AllowMasterKeys {
  1263  			// nothing defined, add key to ALL
  1264  			log.WithFields(logrus.Fields{
  1265  				"prefix":      "api",
  1266  				"status":      "warning",
  1267  				"org_id":      newSession.OrgID,
  1268  				"api_id":      "--",
  1269  				"user_id":     "system",
  1270  				"user_ip":     requestIPHops(r),
  1271  				"path":        "--",
  1272  				"server_name": "system",
  1273  			}).Warning("No API Access Rights set on key session, adding key to all APIs.")
  1274  
  1275  			apisMu.RLock()
  1276  			defer apisMu.RUnlock()
  1277  			for _, spec := range apisByID {
  1278  				checkAndApplyTrialPeriod(newKey, spec.APIID, newSession, false)
  1279  				if !spec.DontSetQuotasOnCreate {
  1280  					// Reset quote by default
  1281  					spec.SessionManager.ResetQuota(newKey, newSession, false)
  1282  					newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
  1283  				}
  1284  				// apply polices (if any) and save key
  1285  				if err := applyPoliciesAndSave(newKey, newSession, spec, false); err != nil {
  1286  					doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error()))
  1287  					return
  1288  				}
  1289  			}
  1290  		} else {
  1291  			log.WithFields(logrus.Fields{
  1292  				"prefix":      "api",
  1293  				"status":      "error",
  1294  				"err":         "master keys disabled",
  1295  				"org_id":      newSession.OrgID,
  1296  				"api_id":      "--",
  1297  				"user_id":     "system",
  1298  				"user_ip":     requestIPHops(r),
  1299  				"path":        "--",
  1300  				"server_name": "system",
  1301  			}).Error("Master keys disallowed in configuration, key not added.")
  1302  
  1303  			doJSONWrite(w, http.StatusBadRequest, apiError("Failed to create key, keys must have at least one Access Rights record set."))
  1304  			return
  1305  		}
  1306  
  1307  	}
  1308  
  1309  	obj := apiModifyKeySuccess{
  1310  		Action: "added",
  1311  		Key:    newKey,
  1312  		Status: "ok",
  1313  	}
  1314  
  1315  	// add key hash to reply
  1316  	if config.Global().HashKeys {
  1317  		obj.KeyHash = storage.HashKey(newKey)
  1318  	}
  1319  
  1320  	FireSystemEvent(EventTokenCreated, EventTokenMeta{
  1321  		EventMetaDefault: EventMetaDefault{Message: "Key generated."},
  1322  		Org:              newSession.OrgID,
  1323  		Key:              newKey,
  1324  	})
  1325  
  1326  	log.WithFields(logrus.Fields{
  1327  		"prefix":      "api",
  1328  		"key":         obfuscateKey(newKey),
  1329  		"status":      "ok",
  1330  		"api_id":      "--",
  1331  		"org_id":      newSession.OrgID,
  1332  		"user_id":     "system",
  1333  		"user_ip":     requestIPHops(r),
  1334  		"path":        "--",
  1335  		"server_name": "system",
  1336  	}).Info("Generated new key: (", obfuscateKey(newKey), ")")
  1337  
  1338  	doJSONWrite(w, http.StatusOK, obj)
  1339  }
  1340  
  1341  // NewClientRequest is an outward facing JSON object translated from osin OAuthClients
  1342  //
  1343  // swagger:model NewClientRequest
  1344  type NewClientRequest struct {
  1345  	ClientID          string      `json:"client_id"`
  1346  	ClientRedirectURI string      `json:"redirect_uri"`
  1347  	APIID             string      `json:"api_id,omitempty"`
  1348  	PolicyID          string      `json:"policy_id,omitempty"`
  1349  	ClientSecret      string      `json:"secret"`
  1350  	MetaData          interface{} `json:"meta_data"`
  1351  	Description       string      `json:"description"`
  1352  }
  1353  
  1354  func oauthClientStorageID(clientID string) string {
  1355  	return prefixClient + clientID
  1356  }
  1357  
  1358  func createOauthClient(w http.ResponseWriter, r *http.Request) {
  1359  	var newOauthClient NewClientRequest
  1360  	if err := json.NewDecoder(r.Body).Decode(&newOauthClient); err != nil {
  1361  		log.WithFields(logrus.Fields{
  1362  			"prefix": "api",
  1363  			"status": "fail",
  1364  			"err":    err,
  1365  		}).Error("Failed to create OAuth client")
  1366  		doJSONWrite(w, http.StatusInternalServerError, apiError("Unmarshalling failed"))
  1367  		return
  1368  	}
  1369  
  1370  	// Allow the client ID to be set
  1371  	cleanSting := newOauthClient.ClientID
  1372  
  1373  	if newOauthClient.ClientID == "" {
  1374  		u5 := uuid.NewV4()
  1375  		cleanSting = strings.Replace(u5.String(), "-", "", -1)
  1376  	}
  1377  
  1378  	// Allow the secret to be set
  1379  	secret := newOauthClient.ClientSecret
  1380  	if newOauthClient.ClientSecret == "" {
  1381  		u5Secret := uuid.NewV4()
  1382  		secret = base64.StdEncoding.EncodeToString([]byte(u5Secret.String()))
  1383  	}
  1384  
  1385  	newClient := OAuthClient{
  1386  		ClientID:          cleanSting,
  1387  		ClientRedirectURI: newOauthClient.ClientRedirectURI,
  1388  		ClientSecret:      secret,
  1389  		PolicyID:          newOauthClient.PolicyID,
  1390  		MetaData:          newOauthClient.MetaData,
  1391  		Description:       newOauthClient.Description,
  1392  	}
  1393  
  1394  	storageID := oauthClientStorageID(newClient.GetId())
  1395  	log.WithFields(logrus.Fields{
  1396  		"prefix": "api",
  1397  	}).Debug("Created storage ID: ", storageID)
  1398  
  1399  	if newOauthClient.APIID != "" {
  1400  		// set client only for passed API ID
  1401  		apiSpec := getApiSpec(newOauthClient.APIID)
  1402  		if apiSpec == nil {
  1403  			log.WithFields(logrus.Fields{
  1404  				"prefix": "api",
  1405  				"apiID":  newOauthClient.APIID,
  1406  				"status": "fail",
  1407  				"err":    "API doesn't exist",
  1408  			}).Error("Failed to create OAuth client")
  1409  			doJSONWrite(w, http.StatusBadRequest, apiError("API doesn't exist"))
  1410  			return
  1411  		}
  1412  
  1413  		if !apiSpec.UseOauth2 {
  1414  			doJSONWrite(w, http.StatusBadRequest,
  1415  				apiError("API is not OAuth2"))
  1416  			return
  1417  		}
  1418  
  1419  		err := apiSpec.OAuthManager.OsinServer.Storage.SetClient(storageID, &newClient, true)
  1420  		if err != nil {
  1421  			log.WithFields(logrus.Fields{
  1422  				"prefix": "api",
  1423  				"apiID":  newOauthClient.APIID,
  1424  				"status": "fail",
  1425  				"err":    err,
  1426  			}).Error("Failed to create OAuth client")
  1427  			doJSONWrite(w, http.StatusInternalServerError, apiError("Failure in storing client data."))
  1428  			return
  1429  		}
  1430  	} else {
  1431  		// set client for all APIs from the given policy
  1432  		policiesMu.RLock()
  1433  		policy, ok := policiesByID[newClient.PolicyID]
  1434  		policiesMu.RUnlock()
  1435  		if !ok {
  1436  			log.WithFields(logrus.Fields{
  1437  				"prefix":   "api",
  1438  				"policyID": newClient.PolicyID,
  1439  				"status":   "fail",
  1440  				"err":      "Policy doesn't exist",
  1441  			}).Error("Failed to create OAuth client")
  1442  			doJSONWrite(w, http.StatusBadRequest, apiError("Policy doesn't exist"))
  1443  			return
  1444  		}
  1445  
  1446  		oauth2 := false
  1447  		// iterate over APIs and set client for each of them
  1448  		for apiID := range policy.AccessRights {
  1449  			apiSpec := getApiSpec(apiID)
  1450  			if apiSpec == nil {
  1451  				log.WithFields(logrus.Fields{
  1452  					"prefix": "api",
  1453  					"apiID":  apiID,
  1454  					"status": "fail",
  1455  					"err":    "API doesn't exist",
  1456  				}).Error("Failed to create OAuth client")
  1457  				doJSONWrite(w, http.StatusBadRequest, apiError("API doesn't exist"))
  1458  				return
  1459  			}
  1460  			// set oauth client if it is oauth API
  1461  			if apiSpec.UseOauth2 {
  1462  				oauth2 = true
  1463  				err := apiSpec.OAuthManager.OsinServer.Storage.SetClient(storageID, &newClient, true)
  1464  				if err != nil {
  1465  					log.WithFields(logrus.Fields{
  1466  						"prefix": "api",
  1467  						"apiID":  apiID,
  1468  						"status": "fail",
  1469  						"err":    err,
  1470  					}).Error("Failed to create OAuth client")
  1471  					doJSONWrite(w, http.StatusInternalServerError, apiError("Failure in storing client data."))
  1472  					return
  1473  				}
  1474  			}
  1475  		}
  1476  
  1477  		if !oauth2 {
  1478  			doJSONWrite(w, http.StatusBadRequest,
  1479  				apiError("API is not OAuth2"))
  1480  			return
  1481  		}
  1482  	}
  1483  
  1484  	clientData := NewClientRequest{
  1485  		ClientID:          newClient.GetId(),
  1486  		ClientSecret:      newClient.GetSecret(),
  1487  		ClientRedirectURI: newClient.GetRedirectUri(),
  1488  		PolicyID:          newClient.GetPolicyID(),
  1489  		MetaData:          newClient.GetUserData(),
  1490  		Description:       newClient.GetDescription(),
  1491  	}
  1492  
  1493  	log.WithFields(logrus.Fields{
  1494  		"prefix":            "api",
  1495  		"apiID":             newOauthClient.APIID,
  1496  		"clientID":          clientData.ClientID,
  1497  		"clientRedirectURI": clientData.ClientRedirectURI,
  1498  		"policyID":          clientData.PolicyID,
  1499  		"description":       clientData.Description,
  1500  		"status":            "ok",
  1501  	}).Info("Created OAuth client")
  1502  
  1503  	doJSONWrite(w, http.StatusOK, clientData)
  1504  }
  1505  
  1506  // Update Client
  1507  func updateOauthClient(keyName, apiID string, r *http.Request) (interface{}, int) {
  1508  	// read payload
  1509  	var updateClientData NewClientRequest
  1510  	if err := json.NewDecoder(r.Body).Decode(&updateClientData); err != nil {
  1511  		log.WithFields(logrus.Fields{
  1512  			"prefix": "api",
  1513  			"status": "fail",
  1514  			"err":    err,
  1515  		}).Error("Failed to update OAuth client")
  1516  		return apiError("Unmarshalling failed"), http.StatusInternalServerError
  1517  	}
  1518  
  1519  	// check API
  1520  	apiSpec := getApiSpec(apiID)
  1521  	if apiSpec == nil {
  1522  		return apiError("API doesn't exist"), http.StatusNotFound
  1523  	}
  1524  
  1525  	// check policy
  1526  	if updateClientData.PolicyID != "" {
  1527  		policiesMu.RLock()
  1528  		policy, ok := policiesByID[updateClientData.PolicyID]
  1529  		policiesMu.RUnlock()
  1530  		if !ok {
  1531  			return apiError("Policy doesn't exist"), http.StatusNotFound
  1532  		}
  1533  		if _, ok := policy.AccessRights[apiID]; !ok {
  1534  			return apiError("Policy access rights doesn't contain API this OAuth client belongs to"),
  1535  				http.StatusBadRequest
  1536  		}
  1537  		if len(policy.AccessRights) != 1 {
  1538  			return apiError("Policy access rights should contain only one API"), http.StatusBadRequest
  1539  		}
  1540  	}
  1541  
  1542  	// get existing version of oauth-client
  1543  	storageID := oauthClientStorageID(keyName)
  1544  	client, err := apiSpec.OAuthManager.OsinServer.Storage.GetExtendedClientNoPrefix(storageID)
  1545  	if err != nil {
  1546  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1547  	}
  1548  
  1549  	// update client
  1550  	updatedClient := OAuthClient{
  1551  		ClientID:          client.GetId(),
  1552  		ClientSecret:      client.GetSecret(),                 // DO NOT update
  1553  		ClientRedirectURI: updateClientData.ClientRedirectURI, // update
  1554  		PolicyID:          updateClientData.PolicyID,          // update
  1555  		MetaData:          client.GetUserData(),               // DO NOT update
  1556  		Description:       updateClientData.Description,       // update
  1557  	}
  1558  
  1559  	err = apiSpec.OAuthManager.OsinServer.Storage.SetClient(storageID, &updatedClient, true)
  1560  	if err != nil {
  1561  		log.WithFields(logrus.Fields{
  1562  			"prefix": "api",
  1563  			"apiID":  apiID,
  1564  			"status": "fail",
  1565  			"err":    err,
  1566  		}).Error("Failed to update OAuth client")
  1567  		return apiError("Failure in storing client data"), http.StatusInternalServerError
  1568  	}
  1569  
  1570  	// invalidate tokens if we had a new policy
  1571  	if prevPolicy := client.GetPolicyID(); prevPolicy != "" && prevPolicy != updatedClient.PolicyID {
  1572  		tokenList, err := apiSpec.OAuthManager.OsinServer.Storage.GetClientTokens(updatedClient.ClientID)
  1573  		if err != nil {
  1574  			log.WithError(err).Warning("Could not get list of tokens for updated OAuth client")
  1575  		}
  1576  		for _, token := range tokenList {
  1577  			if err := apiSpec.OAuthManager.OsinServer.Storage.RemoveAccess(token.Token); err != nil {
  1578  				log.WithError(err).Warning("Could not remove token for updated OAuth client policy")
  1579  			}
  1580  		}
  1581  	}
  1582  
  1583  	// convert to outbound format
  1584  	replyData := NewClientRequest{
  1585  		ClientID:          updatedClient.GetId(),
  1586  		ClientSecret:      updatedClient.GetSecret(),
  1587  		ClientRedirectURI: updatedClient.GetRedirectUri(),
  1588  		PolicyID:          updatedClient.GetPolicyID(),
  1589  		MetaData:          updatedClient.GetUserData(),
  1590  		Description:       updatedClient.GetDescription(),
  1591  	}
  1592  
  1593  	return replyData, http.StatusOK
  1594  }
  1595  
  1596  func invalidateOauthRefresh(w http.ResponseWriter, r *http.Request) {
  1597  	apiID := r.URL.Query().Get("api_id")
  1598  	if apiID == "" {
  1599  		doJSONWrite(w, http.StatusBadRequest, apiError("Missing parameter api_id"))
  1600  		return
  1601  	}
  1602  	apiSpec := getApiSpec(apiID)
  1603  
  1604  	log.WithFields(logrus.Fields{
  1605  		"prefix": "api",
  1606  		"apiID":  apiID,
  1607  	}).Debug("Looking for refresh token in API Register")
  1608  
  1609  	if apiSpec == nil {
  1610  		log.WithFields(logrus.Fields{
  1611  			"prefix": "api",
  1612  			"apiID":  apiID,
  1613  			"status": "fail",
  1614  			"err":    "API not found",
  1615  		}).Error("Failed to invalidate refresh token")
  1616  
  1617  		doJSONWrite(w, http.StatusNotFound, apiError("API for this refresh token not found"))
  1618  		return
  1619  	}
  1620  
  1621  	if apiSpec.OAuthManager == nil {
  1622  		log.WithFields(logrus.Fields{
  1623  			"prefix": "api",
  1624  			"apiID":  apiID,
  1625  			"status": "fail",
  1626  			"err":    "API is not OAuth",
  1627  		}).Error("Failed to invalidate refresh token")
  1628  
  1629  		doJSONWrite(w, http.StatusBadRequest, apiError("OAuth is not enabled on this API"))
  1630  		return
  1631  	}
  1632  
  1633  	keyName := mux.Vars(r)["keyName"]
  1634  	err := apiSpec.OAuthManager.OsinServer.Storage.RemoveRefresh(keyName)
  1635  	if err != nil {
  1636  		log.WithFields(logrus.Fields{
  1637  			"prefix": "api",
  1638  			"apiID":  apiID,
  1639  			"status": "fail",
  1640  			"err":    err,
  1641  		}).Error("Failed to invalidate refresh token")
  1642  
  1643  		doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to invalidate refresh token"))
  1644  		return
  1645  	}
  1646  
  1647  	success := apiModifyKeySuccess{
  1648  		Key:    keyName,
  1649  		Status: "ok",
  1650  		Action: "deleted",
  1651  	}
  1652  
  1653  	log.WithFields(logrus.Fields{
  1654  		"prefix": "api",
  1655  		"apiID":  apiID,
  1656  		"token":  keyName,
  1657  		"status": "ok",
  1658  	}).Info("Invalidated refresh token")
  1659  
  1660  	doJSONWrite(w, http.StatusOK, success)
  1661  }
  1662  
  1663  func oAuthClientHandler(w http.ResponseWriter, r *http.Request) {
  1664  	apiID := mux.Vars(r)["apiID"]
  1665  	keyName := mux.Vars(r)["keyName"]
  1666  
  1667  	var obj interface{}
  1668  	var code int
  1669  	switch r.Method {
  1670  	case http.MethodGet:
  1671  		if keyName != "" {
  1672  			// Return single client detail
  1673  			obj, code = getOauthClientDetails(keyName, apiID)
  1674  		} else {
  1675  			// Return list of keys
  1676  			obj, code = getOauthClients(apiID)
  1677  		}
  1678  	case http.MethodPut:
  1679  		// Update client
  1680  		obj, code = updateOauthClient(keyName, apiID, r)
  1681  	case http.MethodDelete:
  1682  		// Remove a key
  1683  		obj, code = handleDeleteOAuthClient(keyName, apiID)
  1684  	}
  1685  
  1686  	doJSONWrite(w, code, obj)
  1687  }
  1688  
  1689  func oAuthClientTokensHandler(w http.ResponseWriter, r *http.Request) {
  1690  	apiID := mux.Vars(r)["apiID"]
  1691  	keyName := mux.Vars(r)["keyName"]
  1692  
  1693  	apiSpec := getApiSpec(apiID)
  1694  	if apiSpec == nil {
  1695  		log.WithFields(logrus.Fields{
  1696  			"prefix": "api",
  1697  			"apiID":  apiID,
  1698  			"status": "fail",
  1699  			"client": keyName,
  1700  			"err":    "not found",
  1701  		}).Error("Failed to retrieve OAuth tokens")
  1702  		doJSONWrite(w, http.StatusNotFound, apiError("OAuth Client ID not found"))
  1703  		return
  1704  	}
  1705  
  1706  	if p := r.URL.Query().Get("page"); p != "" {
  1707  		page := 1
  1708  
  1709  		queryPage, err := strconv.Atoi(p)
  1710  		if err == nil {
  1711  			page = queryPage
  1712  		}
  1713  
  1714  		if page <= 0 {
  1715  			page = 1
  1716  		}
  1717  
  1718  		tokens, totalPages, err := apiSpec.OAuthManager.OsinServer.Storage.GetPaginatedClientTokens(keyName, page)
  1719  		if err != nil {
  1720  			doJSONWrite(w, http.StatusInternalServerError, apiError("Get client tokens failed"))
  1721  			return
  1722  		}
  1723  
  1724  		doJSONWrite(w, http.StatusOK, paginatedOAuthClientTokens{
  1725  			Pagination: paginationStatus{
  1726  				PageSize:  100,
  1727  				PageNum:   page,
  1728  				PageTotal: totalPages,
  1729  			},
  1730  			Tokens: tokens,
  1731  		})
  1732  
  1733  		return
  1734  	}
  1735  
  1736  	tokens, err := apiSpec.OAuthManager.OsinServer.Storage.GetClientTokens(keyName)
  1737  	if err != nil {
  1738  		doJSONWrite(w, http.StatusInternalServerError, apiError("Get client tokens failed"))
  1739  		return
  1740  	}
  1741  
  1742  	doJSONWrite(w, http.StatusOK, tokens)
  1743  }
  1744  
  1745  // Get client details
  1746  func getOauthClientDetails(keyName, apiID string) (interface{}, int) {
  1747  	storageID := oauthClientStorageID(keyName)
  1748  	apiSpec := getApiSpec(apiID)
  1749  	if apiSpec == nil {
  1750  		log.WithFields(logrus.Fields{
  1751  			"prefix": "api",
  1752  			"apiID":  apiID,
  1753  			"status": "fail",
  1754  			"client": keyName,
  1755  			"err":    "not found",
  1756  		}).Error("Failed to retrieve OAuth client details")
  1757  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1758  	}
  1759  
  1760  	clientData, err := apiSpec.OAuthManager.OsinServer.Storage.GetExtendedClientNoPrefix(storageID)
  1761  	if err != nil {
  1762  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1763  	}
  1764  	reportableClientData := NewClientRequest{
  1765  		ClientID:          clientData.GetId(),
  1766  		ClientSecret:      clientData.GetSecret(),
  1767  		ClientRedirectURI: clientData.GetRedirectUri(),
  1768  		PolicyID:          clientData.GetPolicyID(),
  1769  		MetaData:          clientData.GetUserData(),
  1770  		Description:       clientData.GetDescription(),
  1771  	}
  1772  
  1773  	log.WithFields(logrus.Fields{
  1774  		"prefix": "api",
  1775  		"apiID":  apiID,
  1776  		"status": "ok",
  1777  		"client": keyName,
  1778  	}).Info("Retrieved OAuth client ID")
  1779  
  1780  	return reportableClientData, http.StatusOK
  1781  }
  1782  
  1783  // Delete Client
  1784  func handleDeleteOAuthClient(keyName, apiID string) (interface{}, int) {
  1785  	storageID := oauthClientStorageID(keyName)
  1786  
  1787  	apiSpec := getApiSpec(apiID)
  1788  	if apiSpec == nil {
  1789  		log.WithFields(logrus.Fields{
  1790  			"prefix": "api",
  1791  			"apiID":  apiID,
  1792  			"status": "fail",
  1793  			"client": keyName,
  1794  			"err":    "not found",
  1795  		}).Error("Failed to delete OAuth client")
  1796  
  1797  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1798  	}
  1799  
  1800  	err := apiSpec.OAuthManager.OsinServer.Storage.DeleteClient(storageID, true)
  1801  	if err != nil {
  1802  		return apiError("Delete failed"), http.StatusInternalServerError
  1803  	}
  1804  
  1805  	statusObj := apiModifyKeySuccess{
  1806  		Key:    keyName,
  1807  		Status: "ok",
  1808  		Action: "deleted",
  1809  	}
  1810  
  1811  	log.WithFields(logrus.Fields{
  1812  		"prefix": "api",
  1813  		"apiID":  apiID,
  1814  		"status": "ok",
  1815  		"client": keyName,
  1816  	}).Info("Deleted OAuth client")
  1817  
  1818  	return statusObj, http.StatusOK
  1819  }
  1820  
  1821  const oAuthNotPropagatedErr = "OAuth client list isn't available or hasn't been propagated yet."
  1822  
  1823  // List Clients
  1824  func getOauthClients(apiID string) (interface{}, int) {
  1825  	filterID := prefixClient
  1826  
  1827  	apiSpec := getApiSpec(apiID)
  1828  	if apiSpec == nil {
  1829  		log.WithFields(logrus.Fields{
  1830  			"prefix": "api",
  1831  			"apiID":  apiID,
  1832  			"status": "fail",
  1833  			"err":    "API not found",
  1834  		}).Error("Failed to retrieve OAuth client list.")
  1835  
  1836  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1837  	}
  1838  
  1839  	if apiSpec.OAuthManager == nil {
  1840  		log.WithFields(logrus.Fields{
  1841  			"prefix": "api",
  1842  			"apiID":  apiID,
  1843  			"status": "fail",
  1844  			"err":    "API not found",
  1845  		}).Error("Failed to retrieve OAuth client list.")
  1846  
  1847  		return apiError(oAuthNotPropagatedErr), http.StatusBadRequest
  1848  	}
  1849  
  1850  	clientData, err := apiSpec.OAuthManager.OsinServer.Storage.GetClients(filterID, true)
  1851  	if err != nil {
  1852  		log.WithFields(logrus.Fields{
  1853  			"prefix": "api",
  1854  			"apiID":  apiID,
  1855  			"status": "fail",
  1856  			"err":    err,
  1857  		}).Error("Failed to report OAuth client list")
  1858  
  1859  		return apiError("OAuth slients not found"), http.StatusNotFound
  1860  	}
  1861  	clients := []NewClientRequest{}
  1862  	for _, osinClient := range clientData {
  1863  		reportableClientData := NewClientRequest{
  1864  			ClientID:          osinClient.GetId(),
  1865  			ClientSecret:      osinClient.GetSecret(),
  1866  			ClientRedirectURI: osinClient.GetRedirectUri(),
  1867  			PolicyID:          osinClient.GetPolicyID(),
  1868  			MetaData:          osinClient.GetUserData(),
  1869  			Description:       osinClient.GetDescription(),
  1870  		}
  1871  
  1872  		clients = append(clients, reportableClientData)
  1873  	}
  1874  	log.WithFields(logrus.Fields{
  1875  		"prefix": "api",
  1876  		"apiID":  apiID,
  1877  		"status": "ok",
  1878  	}).Info("Retrieved OAuth client list")
  1879  
  1880  	return clients, http.StatusOK
  1881  }
  1882  
  1883  func healthCheckhandler(w http.ResponseWriter, r *http.Request) {
  1884  	if !config.Global().HealthCheck.EnableHealthChecks {
  1885  		doJSONWrite(w, http.StatusBadRequest, apiError("Health checks are not enabled for this node"))
  1886  		return
  1887  	}
  1888  	apiID := r.URL.Query().Get("api_id")
  1889  	if apiID == "" {
  1890  		doJSONWrite(w, http.StatusBadRequest, apiError("missing api_id parameter"))
  1891  		return
  1892  	}
  1893  	apiSpec := getApiSpec(apiID)
  1894  	if apiSpec == nil {
  1895  		doJSONWrite(w, http.StatusNotFound, apiError("API ID not found"))
  1896  		return
  1897  	}
  1898  	health, _ := apiSpec.Health.ApiHealthValues()
  1899  	doJSONWrite(w, http.StatusOK, health)
  1900  }
  1901  
  1902  func userRatesCheck(w http.ResponseWriter, r *http.Request) {
  1903  	session := ctxGetSession(r)
  1904  	if session == nil {
  1905  		doJSONWrite(w, http.StatusBadRequest, apiError("Health checks are not enabled for this node"))
  1906  		return
  1907  	}
  1908  
  1909  	returnSession := PublicSession{}
  1910  	returnSession.Quota.QuotaRenews = session.QuotaRenews
  1911  	returnSession.Quota.QuotaRemaining = session.QuotaRemaining
  1912  	returnSession.Quota.QuotaMax = session.QuotaMax
  1913  	returnSession.RateLimit.Rate = session.Rate
  1914  	returnSession.RateLimit.Per = session.Per
  1915  
  1916  	doJSONWrite(w, http.StatusOK, returnSession)
  1917  }
  1918  
  1919  func invalidateCacheHandler(w http.ResponseWriter, r *http.Request) {
  1920  	apiID := mux.Vars(r)["apiID"]
  1921  
  1922  	keyPrefix := "cache-" + apiID
  1923  	matchPattern := keyPrefix + "*"
  1924  	store := storage.RedisCluster{KeyPrefix: keyPrefix, IsCache: true}
  1925  
  1926  	if ok := store.DeleteScanMatch(matchPattern); !ok {
  1927  		err := errors.New("scan/delete failed")
  1928  		var orgid string
  1929  		if spec := getApiSpec(apiID); spec != nil {
  1930  			orgid = spec.OrgID
  1931  		}
  1932  		log.WithFields(logrus.Fields{
  1933  			"prefix":      "api",
  1934  			"api_id":      apiID,
  1935  			"status":      "fail",
  1936  			"err":         err,
  1937  			"org_id":      orgid,
  1938  			"user_id":     "system",
  1939  			"user_ip":     requestIPHops(r),
  1940  			"path":        "--",
  1941  			"server_name": "system",
  1942  		}).Error("Failed to delete cache: ", err)
  1943  
  1944  		doJSONWrite(w, http.StatusInternalServerError, apiError("Cache invalidation failed"))
  1945  		return
  1946  	}
  1947  
  1948  	doJSONWrite(w, http.StatusOK, apiOk("cache invalidated"))
  1949  }
  1950  
  1951  // TODO: Don't modify http.Request values in-place. We must right now
  1952  // because our middleware design doesn't pass around http.Request
  1953  // pointers, so we have no way to modify the pointer in a middleware.
  1954  //
  1955  // If we ever redesign middlewares - or if we find another workaround -
  1956  // revisit this.
  1957  func setContext(r *http.Request, ctx context.Context) {
  1958  	r2 := r.WithContext(ctx)
  1959  	*r = *r2
  1960  }
  1961  func setCtxValue(r *http.Request, key, val interface{}) {
  1962  	setContext(r, context.WithValue(r.Context(), key, val))
  1963  }
  1964  
  1965  func ctxGetData(r *http.Request) map[string]interface{} {
  1966  	if v := r.Context().Value(ctx.ContextData); v != nil {
  1967  		return v.(map[string]interface{})
  1968  	}
  1969  	return nil
  1970  }
  1971  
  1972  func ctxSetData(r *http.Request, m map[string]interface{}) {
  1973  	if m == nil {
  1974  		panic("setting a nil context ContextData")
  1975  	}
  1976  	setCtxValue(r, ctx.ContextData, m)
  1977  }
  1978  
  1979  func ctxGetSession(r *http.Request) *user.SessionState {
  1980  	return ctx.GetSession(r)
  1981  }
  1982  
  1983  func ctxSetSession(r *http.Request, s *user.SessionState, token string, scheduleUpdate bool) {
  1984  	ctx.SetSession(r, s, token, scheduleUpdate)
  1985  }
  1986  
  1987  func ctxScheduleSessionUpdate(r *http.Request) {
  1988  	setCtxValue(r, ctx.UpdateSession, true)
  1989  }
  1990  
  1991  func ctxDisableSessionUpdate(r *http.Request) {
  1992  	setCtxValue(r, ctx.UpdateSession, false)
  1993  }
  1994  
  1995  func ctxSessionUpdateScheduled(r *http.Request) bool {
  1996  	if v := r.Context().Value(ctx.UpdateSession); v != nil {
  1997  		return v.(bool)
  1998  	}
  1999  	return false
  2000  }
  2001  
  2002  func ctxGetAuthToken(r *http.Request) string {
  2003  	return ctx.GetAuthToken(r)
  2004  }
  2005  
  2006  func ctxGetTrackedPath(r *http.Request) string {
  2007  	if v := r.Context().Value(ctx.TrackThisEndpoint); v != nil {
  2008  		return v.(string)
  2009  	}
  2010  	return ""
  2011  }
  2012  
  2013  func ctxSetTrackedPath(r *http.Request, p string) {
  2014  	if p == "" {
  2015  		panic("setting a nil context TrackThisEndpoint")
  2016  	}
  2017  	setCtxValue(r, ctx.TrackThisEndpoint, p)
  2018  }
  2019  
  2020  func ctxGetDoNotTrack(r *http.Request) bool {
  2021  	return r.Context().Value(ctx.DoNotTrackThisEndpoint) == true
  2022  }
  2023  
  2024  func ctxSetDoNotTrack(r *http.Request, b bool) {
  2025  	setCtxValue(r, ctx.DoNotTrackThisEndpoint, b)
  2026  }
  2027  
  2028  func ctxGetVersionInfo(r *http.Request) *apidef.VersionInfo {
  2029  	if v := r.Context().Value(ctx.VersionData); v != nil {
  2030  		return v.(*apidef.VersionInfo)
  2031  	}
  2032  	return nil
  2033  }
  2034  
  2035  func ctxSetVersionInfo(r *http.Request, v *apidef.VersionInfo) {
  2036  	setCtxValue(r, ctx.VersionData, v)
  2037  }
  2038  
  2039  func ctxSetOrigRequestURL(r *http.Request, url *url.URL) {
  2040  	setCtxValue(r, ctx.OrigRequestURL, url)
  2041  }
  2042  
  2043  func ctxGetOrigRequestURL(r *http.Request) *url.URL {
  2044  	if v := r.Context().Value(ctx.OrigRequestURL); v != nil {
  2045  		if urlVal, ok := v.(*url.URL); ok {
  2046  			return urlVal
  2047  		}
  2048  	}
  2049  
  2050  	return nil
  2051  }
  2052  
  2053  func ctxSetUrlRewritePath(r *http.Request, path string) {
  2054  	setCtxValue(r, ctx.UrlRewritePath, path)
  2055  }
  2056  
  2057  func ctxGetUrlRewritePath(r *http.Request) string {
  2058  	if v := r.Context().Value(ctx.UrlRewritePath); v != nil {
  2059  		if strVal, ok := v.(string); ok {
  2060  			return strVal
  2061  		}
  2062  	}
  2063  	return ""
  2064  }
  2065  
  2066  func ctxSetCheckLoopLimits(r *http.Request, b bool) {
  2067  	setCtxValue(r, ctx.CheckLoopLimits, b)
  2068  }
  2069  
  2070  // Should we check Rate limits and Quotas?
  2071  func ctxCheckLimits(r *http.Request) bool {
  2072  	// If looping disabled, allow all
  2073  	if !ctxLoopingEnabled(r) {
  2074  		return true
  2075  	}
  2076  
  2077  	if v := r.Context().Value(ctx.CheckLoopLimits); v != nil {
  2078  		return v.(bool)
  2079  	}
  2080  
  2081  	return false
  2082  }
  2083  
  2084  func ctxSetRequestMethod(r *http.Request, path string) {
  2085  	setCtxValue(r, ctx.RequestMethod, path)
  2086  }
  2087  
  2088  func ctxGetRequestMethod(r *http.Request) string {
  2089  	if v := r.Context().Value(ctx.RequestMethod); v != nil {
  2090  		if strVal, ok := v.(string); ok {
  2091  			return strVal
  2092  		}
  2093  	}
  2094  	return r.Method
  2095  }
  2096  
  2097  func ctxGetDefaultVersion(r *http.Request) bool {
  2098  	return r.Context().Value(ctx.VersionDefault) != nil
  2099  }
  2100  
  2101  func ctxSetDefaultVersion(r *http.Request) {
  2102  	setCtxValue(r, ctx.VersionDefault, true)
  2103  }
  2104  
  2105  func ctxLoopingEnabled(r *http.Request) bool {
  2106  	return ctxLoopLevel(r) > 0
  2107  }
  2108  
  2109  func ctxLoopLevel(r *http.Request) int {
  2110  	if v := r.Context().Value(ctx.LoopLevel); v != nil {
  2111  		if intVal, ok := v.(int); ok {
  2112  			return intVal
  2113  		}
  2114  	}
  2115  
  2116  	return 0
  2117  }
  2118  
  2119  func ctxSetLoopLevel(r *http.Request, value int) {
  2120  	setCtxValue(r, ctx.LoopLevel, value)
  2121  }
  2122  
  2123  func ctxIncLoopLevel(r *http.Request, loopLimit int) {
  2124  	ctxSetLoopLimit(r, loopLimit)
  2125  	ctxSetLoopLevel(r, ctxLoopLevel(r)+1)
  2126  }
  2127  
  2128  func ctxLoopLevelLimit(r *http.Request) int {
  2129  	if v := r.Context().Value(ctx.LoopLevelLimit); v != nil {
  2130  		if intVal, ok := v.(int); ok {
  2131  			return intVal
  2132  		}
  2133  	}
  2134  
  2135  	return 0
  2136  }
  2137  
  2138  func ctxSetLoopLimit(r *http.Request, limit int) {
  2139  	// Can be set only one time per request
  2140  	if ctxLoopLevelLimit(r) == 0 && limit > 0 {
  2141  		setCtxValue(r, ctx.LoopLevelLimit, limit)
  2142  	}
  2143  }
  2144  
  2145  func ctxThrottleLevelLimit(r *http.Request) int {
  2146  	if v := r.Context().Value(ctx.ThrottleLevelLimit); v != nil {
  2147  		if intVal, ok := v.(int); ok {
  2148  			return intVal
  2149  		}
  2150  	}
  2151  
  2152  	return 0
  2153  }
  2154  
  2155  func ctxThrottleLevel(r *http.Request) int {
  2156  	if v := r.Context().Value(ctx.ThrottleLevel); v != nil {
  2157  		if intVal, ok := v.(int); ok {
  2158  			return intVal
  2159  		}
  2160  	}
  2161  
  2162  	return 0
  2163  }
  2164  
  2165  func ctxSetThrottleLimit(r *http.Request, limit int) {
  2166  	// Can be set only one time per request
  2167  	if ctxThrottleLevelLimit(r) == 0 && limit > 0 {
  2168  		setCtxValue(r, ctx.ThrottleLevelLimit, limit)
  2169  	}
  2170  }
  2171  
  2172  func ctxSetThrottleLevel(r *http.Request, value int) {
  2173  	setCtxValue(r, ctx.ThrottleLevel, value)
  2174  }
  2175  
  2176  func ctxIncThrottleLevel(r *http.Request, throttleLimit int) {
  2177  	ctxSetThrottleLimit(r, throttleLimit)
  2178  	ctxSetThrottleLevel(r, ctxThrottleLevel(r)+1)
  2179  }
  2180  
  2181  func ctxTraceEnabled(r *http.Request) bool {
  2182  	return r.Context().Value(ctx.Trace) != nil
  2183  }
  2184  
  2185  func ctxSetTrace(r *http.Request) {
  2186  	setCtxValue(r, ctx.Trace, true)
  2187  }