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