github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/manager/manager.go (about) 1 package manager 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "net" 9 "net/http" 10 "strings" 11 "sync" 12 "time" 13 14 log "github.com/Sirupsen/logrus" 15 "github.com/gorilla/sessions" 16 "github.com/samalba/dockerclient" 17 "github.com/shipyard/shipyard" 18 "github.com/shipyard/shipyard/auth" 19 "github.com/shipyard/shipyard/dockerhub" 20 "github.com/shipyard/shipyard/version" 21 r "gopkg.in/dancannon/gorethink.v2" 22 ) 23 24 const ( 25 tblNameConfig = "config" 26 tblNameEvents = "events" 27 tblNameAccounts = "accounts" 28 tblNameRoles = "roles" 29 tblNameServiceKeys = "service_keys" 30 tblNameExtensions = "extensions" 31 tblNameWebhookKeys = "webhook_keys" 32 tblNameRegistries = "registries" 33 tblNameConsole = "console" 34 storeKey = "shipyard" 35 trackerHost = "http://tracker.shipyard-project.com" 36 NodeHealthUp = "up" 37 NodeHealthDown = "down" 38 ) 39 40 var ( 41 ErrLoginFailure = errors.New("invalid username or password") 42 ErrAccountExists = errors.New("account already exists") 43 ErrAccountDoesNotExist = errors.New("account does not exist") 44 ErrRoleDoesNotExist = errors.New("role does not exist") 45 ErrNodeDoesNotExist = errors.New("node does not exist") 46 ErrServiceKeyDoesNotExist = errors.New("service key does not exist") 47 ErrInvalidAuthToken = errors.New("invalid auth token") 48 ErrExtensionDoesNotExist = errors.New("extension does not exist") 49 ErrWebhookKeyDoesNotExist = errors.New("webhook key does not exist") 50 ErrRegistryDoesNotExist = errors.New("registry does not exist") 51 ErrConsoleSessionDoesNotExist = errors.New("console session does not exist") 52 store = sessions.NewCookieStore([]byte(storeKey)) 53 ) 54 55 type ( 56 DefaultManager struct { 57 storeKey string 58 database string 59 authKey string 60 session *r.Session 61 authenticator auth.Authenticator 62 store *sessions.CookieStore 63 client *dockerclient.DockerClient 64 disableUsageInfo bool 65 } 66 67 ScaleResult struct { 68 Scaled []string 69 Errors []string 70 } 71 72 Manager interface { 73 Accounts() ([]*auth.Account, error) 74 Account(username string) (*auth.Account, error) 75 Authenticate(username, password string) (bool, error) 76 GetAuthenticator() auth.Authenticator 77 SaveAccount(account *auth.Account) error 78 DeleteAccount(account *auth.Account) error 79 Roles() ([]*auth.ACL, error) 80 Role(name string) (*auth.ACL, error) 81 Store() *sessions.CookieStore 82 StoreKey() string 83 Container(id string) (*dockerclient.ContainerInfo, error) 84 ScaleContainer(id string, numInstances int) ScaleResult 85 SaveServiceKey(key *auth.ServiceKey) error 86 RemoveServiceKey(key string) error 87 SaveEvent(event *shipyard.Event) error 88 Events(limit int) ([]*shipyard.Event, error) 89 PurgeEvents() error 90 ServiceKey(key string) (*auth.ServiceKey, error) 91 ServiceKeys() ([]*auth.ServiceKey, error) 92 NewAuthToken(username string, userAgent string) (*auth.AuthToken, error) 93 VerifyAuthToken(username, token string) error 94 VerifyServiceKey(key string) error 95 NewServiceKey(description string) (*auth.ServiceKey, error) 96 ChangePassword(username, password string) error 97 WebhookKey(key string) (*dockerhub.WebhookKey, error) 98 WebhookKeys() ([]*dockerhub.WebhookKey, error) 99 NewWebhookKey(image string) (*dockerhub.WebhookKey, error) 100 SaveWebhookKey(key *dockerhub.WebhookKey) error 101 DeleteWebhookKey(id string) error 102 DockerClient() *dockerclient.DockerClient 103 104 Nodes() ([]*shipyard.Node, error) 105 Node(name string) (*shipyard.Node, error) 106 107 AddRegistry(registry *shipyard.Registry) error 108 RemoveRegistry(registry *shipyard.Registry) error 109 Registries() ([]*shipyard.Registry, error) 110 Registry(name string) (*shipyard.Registry, error) 111 112 CreateConsoleSession(c *shipyard.ConsoleSession) error 113 RemoveConsoleSession(c *shipyard.ConsoleSession) error 114 ConsoleSession(token string) (*shipyard.ConsoleSession, error) 115 ValidateConsoleSessionToken(containerId, token string) bool 116 } 117 ) 118 119 func NewManager(addr string, database string, authKey string, client *dockerclient.DockerClient, disableUsageInfo bool, authenticator auth.Authenticator) (Manager, error) { 120 log.Debug("setting up rethinkdb session") 121 session, err := r.Connect(r.ConnectOpts{ 122 Address: addr, 123 Database: database, 124 AuthKey: authKey, 125 }) 126 if err != nil { 127 return nil, err 128 } 129 log.Info("checking database") 130 131 r.DBCreate(database).Run(session) 132 m := &DefaultManager{ 133 database: database, 134 authKey: authKey, 135 session: session, 136 authenticator: authenticator, 137 store: store, 138 client: client, 139 storeKey: storeKey, 140 disableUsageInfo: disableUsageInfo, 141 } 142 m.initdb() 143 m.init() 144 return m, nil 145 } 146 147 func (m DefaultManager) Store() *sessions.CookieStore { 148 return m.store 149 } 150 151 func (m DefaultManager) DockerClient() *dockerclient.DockerClient { 152 return m.client 153 } 154 155 func (m DefaultManager) StoreKey() string { 156 return m.storeKey 157 } 158 159 func (m DefaultManager) initdb() { 160 // create tables if needed 161 tables := []string{tblNameConfig, tblNameEvents, tblNameAccounts, tblNameRoles, tblNameConsole, tblNameServiceKeys, tblNameRegistries, tblNameExtensions, tblNameWebhookKeys} 162 for _, tbl := range tables { 163 _, err := r.Table(tbl).Run(m.session) 164 if err != nil { 165 if _, err := r.DB(m.database).TableCreate(tbl).Run(m.session); err != nil { 166 log.Fatalf("error creating table: %s", err) 167 } 168 } 169 } 170 } 171 172 func (m DefaultManager) init() error { 173 // anonymous usage info 174 go m.usageReport() 175 return nil 176 } 177 178 func (m DefaultManager) logEvent(eventType, message string, tags []string) { 179 evt := &shipyard.Event{ 180 Type: eventType, 181 Time: time.Now(), 182 Message: message, 183 Tags: tags, 184 } 185 186 if err := m.SaveEvent(evt); err != nil { 187 log.Errorf("error logging event: %s", err) 188 } 189 } 190 191 func (m DefaultManager) usageReport() { 192 if m.disableUsageInfo { 193 return 194 } 195 m.uploadUsage() 196 t := time.NewTicker(1 * time.Hour).C 197 for { 198 select { 199 case <-t: 200 go m.uploadUsage() 201 } 202 } 203 } 204 205 func (m DefaultManager) uploadUsage() { 206 id := "anon" 207 ifaces, err := net.Interfaces() 208 if err == nil { 209 for _, iface := range ifaces { 210 if iface.Name != "lo" { 211 hw := iface.HardwareAddr.String() 212 id = strings.Replace(hw, ":", "", -1) 213 break 214 } 215 } 216 } 217 usage := &shipyard.Usage{ 218 ID: id, 219 Version: version.Version, 220 } 221 b, err := json.Marshal(usage) 222 if err != nil { 223 log.Warnf("error serializing usage info: %s", err) 224 } 225 buf := bytes.NewBuffer(b) 226 if _, err := http.Post(fmt.Sprintf("%s/update", trackerHost), "application/json", buf); err != nil { 227 log.Warnf("error sending usage info: %s", err) 228 } 229 } 230 231 func (m DefaultManager) Container(id string) (*dockerclient.ContainerInfo, error) { 232 return m.client.InspectContainer(id) 233 } 234 235 func (m DefaultManager) ScaleContainer(id string, numInstances int) ScaleResult { 236 var ( 237 errChan = make(chan (error)) 238 resChan = make(chan (string)) 239 result = ScaleResult{Scaled: make([]string, 0), Errors: make([]string, 0)} 240 ) 241 242 var lock sync.Mutex 243 244 containerInfo, err := m.Container(id) 245 if err != nil { 246 result.Errors = append(result.Errors, err.Error()) 247 return result 248 } 249 250 fmt.Println("scale container without threads!!!!!") 251 //fmt.Println("scale container with sleep") 252 fmt.Println("try to add mutex") 253 254 for i := 0; i < numInstances; i++ { 255 go func(instance int) { 256 log.Debugf("scaling: id=%s #=%d", containerInfo.Id, instance) 257 config := containerInfo.Config 258 // clear hostname to get a newly generated 259 config.Hostname = "" 260 hostConfig := containerInfo.HostConfig 261 config.HostConfig = *hostConfig // sending hostconfig via the Start-endpoint is deprecated starting with docker-engine 1.12 262 263 lock.Lock() 264 id, err := m.client.CreateContainer(config, "", nil) 265 if err != nil { 266 errChan <- err 267 return 268 } 269 if err := m.client.StartContainer(id, hostConfig); err != nil { 270 errChan <- err 271 return 272 } 273 lock.Unlock() 274 resChan <- id 275 }(i) 276 277 //time.Sleep(time.Second * 10) 278 } 279 280 for i := 0; i < numInstances; i++ { 281 select { 282 case id := <-resChan: 283 result.Scaled = append(result.Scaled, id) 284 case err := <-errChan: 285 log.Errorf("error scaling container: err=%s", strings.TrimSpace(err.Error())) 286 result.Errors = append(result.Errors, strings.TrimSpace(err.Error())) 287 } 288 } 289 290 return result 291 } 292 293 func (m DefaultManager) SaveServiceKey(key *auth.ServiceKey) error { 294 if _, err := r.Table(tblNameServiceKeys).Insert(key).RunWrite(m.session); err != nil { 295 return err 296 } 297 298 m.logEvent("add-service-key", fmt.Sprintf("description=%s", key.Description), []string{"security"}) 299 300 return nil 301 } 302 303 func (m DefaultManager) RemoveServiceKey(key string) error { 304 if _, err := r.Table(tblNameServiceKeys).Filter(map[string]string{"key": key}).Delete().RunWrite(m.session); err != nil { 305 return err 306 } 307 308 m.logEvent("delete-service-key", fmt.Sprintf("key=%s", key), []string{"security"}) 309 310 return nil 311 } 312 313 func (m DefaultManager) SaveEvent(event *shipyard.Event) error { 314 if _, err := r.Table(tblNameEvents).Insert(event).RunWrite(m.session); err != nil { 315 return err 316 } 317 318 return nil 319 } 320 321 func (m DefaultManager) Events(limit int) ([]*shipyard.Event, error) { 322 t := r.Table(tblNameEvents).OrderBy(r.Desc("Time")) 323 if limit > -1 { 324 t.Limit(limit) 325 } 326 res, err := t.Run(m.session) 327 if err != nil { 328 return nil, err 329 } 330 events := []*shipyard.Event{} 331 if err := res.All(&events); err != nil { 332 return nil, err 333 } 334 return events, nil 335 } 336 337 func (m DefaultManager) PurgeEvents() error { 338 if _, err := r.Table(tblNameEvents).Delete().RunWrite(m.session); err != nil { 339 return err 340 } 341 return nil 342 } 343 344 func (m DefaultManager) ServiceKey(key string) (*auth.ServiceKey, error) { 345 res, err := r.Table(tblNameServiceKeys).Filter(map[string]string{"key": key}).Run(m.session) 346 if err != nil { 347 return nil, err 348 349 } 350 if res.IsNil() { 351 return nil, ErrServiceKeyDoesNotExist 352 } 353 var k *auth.ServiceKey 354 if err := res.One(&k); err != nil { 355 return nil, err 356 } 357 return k, nil 358 } 359 360 func (m DefaultManager) ServiceKeys() ([]*auth.ServiceKey, error) { 361 res, err := r.Table(tblNameServiceKeys).Run(m.session) 362 if err != nil { 363 return nil, err 364 } 365 keys := []*auth.ServiceKey{} 366 if err := res.All(&keys); err != nil { 367 return nil, err 368 } 369 return keys, nil 370 } 371 372 func (m DefaultManager) Accounts() ([]*auth.Account, error) { 373 res, err := r.Table(tblNameAccounts).OrderBy(r.Asc("username")).Run(m.session) 374 if err != nil { 375 return nil, err 376 } 377 accounts := []*auth.Account{} 378 if err := res.All(&accounts); err != nil { 379 return nil, err 380 } 381 return accounts, nil 382 } 383 384 func (m DefaultManager) Account(username string) (*auth.Account, error) { 385 res, err := r.Table(tblNameAccounts).Filter(map[string]string{"username": username}).Run(m.session) 386 if err != nil { 387 return nil, err 388 389 } 390 if res.IsNil() { 391 return nil, ErrAccountDoesNotExist 392 } 393 var account *auth.Account 394 if err := res.One(&account); err != nil { 395 return nil, err 396 } 397 return account, nil 398 } 399 400 func (m DefaultManager) SaveAccount(account *auth.Account) error { 401 var ( 402 hash string 403 eventType string 404 ) 405 if account.Password != "" { 406 h, err := auth.Hash(account.Password) 407 if err != nil { 408 return err 409 } 410 411 hash = h 412 } 413 // check if exists; if so, update 414 acct, err := m.Account(account.Username) 415 if err != nil && err != ErrAccountDoesNotExist { 416 return err 417 } 418 419 // update 420 if acct != nil { 421 updates := map[string]interface{}{ 422 "first_name": account.FirstName, 423 "last_name": account.LastName, 424 "roles": account.Roles, 425 } 426 if account.Password != "" { 427 updates["password"] = hash 428 } 429 430 if _, err := r.Table(tblNameAccounts).Filter(map[string]string{"username": account.Username}).Update(updates).RunWrite(m.session); err != nil { 431 return err 432 } 433 434 eventType = "update-account" 435 } else { 436 account.Password = hash 437 if _, err := r.Table(tblNameAccounts).Insert(account).RunWrite(m.session); err != nil { 438 return err 439 } 440 441 eventType = "add-account" 442 } 443 444 m.logEvent(eventType, fmt.Sprintf("username=%s", account.Username), []string{"security"}) 445 446 return nil 447 } 448 449 func (m DefaultManager) DeleteAccount(account *auth.Account) error { 450 res, err := r.Table(tblNameAccounts).Filter(map[string]string{"id": account.ID}).Delete().Run(m.session) 451 if err != nil { 452 return err 453 } 454 455 if res.IsNil() { 456 return ErrAccountDoesNotExist 457 } 458 459 m.logEvent("delete-account", fmt.Sprintf("username=%s", account.Username), []string{"security"}) 460 461 return nil 462 } 463 464 func (m DefaultManager) Roles() ([]*auth.ACL, error) { 465 roles := auth.DefaultACLs() 466 return roles, nil 467 } 468 469 func (m DefaultManager) Role(name string) (*auth.ACL, error) { 470 acls, err := m.Roles() 471 if err != nil { 472 return nil, err 473 } 474 475 for _, r := range acls { 476 if r.RoleName == name { 477 return r, nil 478 } 479 } 480 481 return nil, nil 482 } 483 484 func (m DefaultManager) GetAuthenticator() auth.Authenticator { 485 return m.authenticator 486 } 487 488 func (m DefaultManager) Authenticate(username, password string) (bool, error) { 489 // only get the account to get the hashed password if using the builtin auth 490 passwordHash := "" 491 if m.authenticator.Name() == "builtin" { 492 acct, err := m.Account(username) 493 if err != nil { 494 log.Error(err) 495 return false, ErrLoginFailure 496 } 497 498 passwordHash = acct.Password 499 } 500 501 a, err := m.authenticator.Authenticate(username, password, passwordHash) 502 if !a || err != nil { 503 log.Error(ErrLoginFailure) 504 return false, ErrLoginFailure 505 } 506 507 return true, nil 508 } 509 510 func (m DefaultManager) NewAuthToken(username string, userAgent string) (*auth.AuthToken, error) { 511 tk, err := m.authenticator.GenerateToken() 512 if err != nil { 513 return nil, err 514 } 515 acct, err := m.Account(username) 516 if err != nil { 517 return nil, err 518 } 519 token := &auth.AuthToken{} 520 tokens := acct.Tokens 521 found := false 522 for _, t := range tokens { 523 if t.UserAgent == userAgent { 524 found = true 525 t.Token = tk 526 token = t 527 break 528 } 529 } 530 if !found { 531 token = &auth.AuthToken{ 532 UserAgent: userAgent, 533 Token: tk, 534 } 535 tokens = append(tokens, token) 536 } 537 // delete token 538 if _, err := r.Table(tblNameAccounts).Filter(map[string]string{"username": username}).Filter(r.Row.Field("user_agent").Eq(userAgent)).Delete().Run(m.session); err != nil { 539 return nil, err 540 } 541 // add 542 if _, err := r.Table(tblNameAccounts).Filter(map[string]string{"username": username}).Update(map[string]interface{}{"tokens": tokens}).RunWrite(m.session); err != nil { 543 return nil, err 544 } 545 return token, nil 546 } 547 548 func (m DefaultManager) VerifyAuthToken(username, token string) error { 549 acct, err := m.Account(username) 550 if err != nil { 551 return err 552 } 553 found := false 554 for _, t := range acct.Tokens { 555 if token == t.Token { 556 found = true 557 break 558 } 559 } 560 if !found { 561 return ErrInvalidAuthToken 562 } 563 return nil 564 } 565 566 func (m DefaultManager) VerifyServiceKey(key string) error { 567 if _, err := m.ServiceKey(key); err != nil { 568 return err 569 } 570 return nil 571 } 572 573 func (m DefaultManager) NewServiceKey(description string) (*auth.ServiceKey, error) { 574 k, err := m.authenticator.GenerateToken() 575 if err != nil { 576 return nil, err 577 } 578 key := &auth.ServiceKey{ 579 Key: k[24:], 580 Description: description, 581 } 582 if err := m.SaveServiceKey(key); err != nil { 583 return nil, err 584 } 585 return key, nil 586 } 587 588 func (m DefaultManager) ChangePassword(username, password string) error { 589 if !m.authenticator.IsUpdateSupported() { 590 return fmt.Errorf("not supported for authenticator: %s", m.authenticator.Name()) 591 } 592 593 hash, err := auth.Hash(password) 594 if err != nil { 595 return err 596 } 597 598 if _, err := r.Table(tblNameAccounts).Filter(map[string]string{"username": username}).Update(map[string]string{"password": hash}).Run(m.session); err != nil { 599 return err 600 } 601 602 m.logEvent("change-password", username, []string{"security"}) 603 604 return nil 605 } 606 607 func (m DefaultManager) WebhookKey(key string) (*dockerhub.WebhookKey, error) { 608 res, err := r.Table(tblNameWebhookKeys).Filter(map[string]string{"key": key}).Run(m.session) 609 if err != nil { 610 return nil, err 611 612 } 613 614 if res.IsNil() { 615 return nil, ErrWebhookKeyDoesNotExist 616 617 } 618 619 var k *dockerhub.WebhookKey 620 if err := res.One(&k); err != nil { 621 return nil, err 622 623 } 624 625 return k, nil 626 } 627 628 func (m DefaultManager) WebhookKeys() ([]*dockerhub.WebhookKey, error) { 629 res, err := r.Table(tblNameWebhookKeys).OrderBy(r.Asc("image")).Run(m.session) 630 if err != nil { 631 return nil, err 632 } 633 keys := []*dockerhub.WebhookKey{} 634 if err := res.All(&keys); err != nil { 635 return nil, err 636 } 637 return keys, nil 638 } 639 640 func (m DefaultManager) NewWebhookKey(image string) (*dockerhub.WebhookKey, error) { 641 k := generateId(16) 642 key := &dockerhub.WebhookKey{ 643 Key: k, 644 Image: image, 645 } 646 647 if err := m.SaveWebhookKey(key); err != nil { 648 return nil, err 649 } 650 651 return key, nil 652 } 653 654 func (m DefaultManager) SaveWebhookKey(key *dockerhub.WebhookKey) error { 655 if _, err := r.Table(tblNameWebhookKeys).Insert(key).RunWrite(m.session); err != nil { 656 return err 657 658 } 659 660 m.logEvent("add-webhook-key", fmt.Sprintf("image=%s", key.Image), []string{"webhook"}) 661 662 return nil 663 } 664 665 func (m DefaultManager) DeleteWebhookKey(id string) error { 666 key, err := m.WebhookKey(id) 667 if err != nil { 668 return err 669 670 } 671 res, err := r.Table(tblNameWebhookKeys).Get(key.ID).Delete().Run(m.session) 672 if err != nil { 673 return err 674 675 } 676 677 if res.IsNil() { 678 return ErrWebhookKeyDoesNotExist 679 680 } 681 682 m.logEvent("delete-webhook-key", fmt.Sprintf("image=%s", key.Image), []string{"webhook"}) 683 684 return nil 685 } 686 687 func (m DefaultManager) Nodes() ([]*shipyard.Node, error) { 688 info, err := m.client.Info() 689 if err != nil { 690 return nil, err 691 } 692 693 nodes, err := parseClusterNodes(info.DriverStatus) 694 if err != nil { 695 return nil, err 696 } 697 698 return nodes, nil 699 } 700 701 func (m DefaultManager) Node(name string) (*shipyard.Node, error) { 702 nodes, err := m.Nodes() 703 if err != nil { 704 return nil, err 705 } 706 707 for _, node := range nodes { 708 if node.Name == name { 709 return node, nil 710 } 711 } 712 713 return nil, nil 714 } 715 716 func (m DefaultManager) AddRegistry(registry *shipyard.Registry) error { 717 resp, err := http.Get(fmt.Sprintf("%s/v1/search", registry.Addr)) 718 if err != nil { 719 return err 720 } 721 if resp.StatusCode != 200 { 722 return errors.New(resp.Status) 723 } 724 725 if _, err := r.Table(tblNameRegistries).Insert(registry).RunWrite(m.session); err != nil { 726 return err 727 } 728 729 m.logEvent("add-registry", fmt.Sprintf("name=%s endpoint=%s", registry.Name, registry.Addr), []string{"registry"}) 730 731 return nil 732 } 733 734 func (m DefaultManager) RemoveRegistry(registry *shipyard.Registry) error { 735 res, err := r.Table(tblNameRegistries).Get(registry.ID).Delete().Run(m.session) 736 if err != nil { 737 return err 738 } 739 740 if res.IsNil() { 741 return ErrRegistryDoesNotExist 742 } 743 744 m.logEvent("delete-registry", fmt.Sprintf("name=%s endpoint=%s", registry.Name, registry.Addr), []string{"registry"}) 745 746 return nil 747 } 748 749 func (m DefaultManager) Registries() ([]*shipyard.Registry, error) { 750 res, err := r.Table(tblNameRegistries).OrderBy(r.Asc("name")).Run(m.session) 751 if err != nil { 752 return nil, err 753 } 754 755 regs := []*shipyard.Registry{} 756 if err := res.All(®s); err != nil { 757 return nil, err 758 } 759 760 registries := []*shipyard.Registry{} 761 for _, r := range regs { 762 reg, err := shipyard.NewRegistry(r.ID, r.Name, r.Addr) 763 if err != nil { 764 return nil, err 765 } 766 767 registries = append(registries, reg) 768 } 769 770 return registries, nil 771 } 772 773 func (m DefaultManager) Registry(name string) (*shipyard.Registry, error) { 774 res, err := r.Table(tblNameRegistries).Filter(map[string]string{"name": name}).Run(m.session) 775 if err != nil { 776 return nil, err 777 778 } 779 if res.IsNil() { 780 return nil, ErrRegistryDoesNotExist 781 } 782 var reg *shipyard.Registry 783 if err := res.One(®); err != nil { 784 return nil, err 785 } 786 787 registry, err := shipyard.NewRegistry(reg.ID, reg.Name, reg.Addr) 788 if err != nil { 789 return nil, err 790 } 791 792 return registry, nil 793 } 794 795 func (m DefaultManager) CreateConsoleSession(c *shipyard.ConsoleSession) error { 796 if _, err := r.Table(tblNameConsole).Insert(c).RunWrite(m.session); err != nil { 797 return err 798 } 799 800 m.logEvent("create-console-session", fmt.Sprintf("container=%s", c.ContainerID), []string{"console"}) 801 802 return nil 803 } 804 805 func (m DefaultManager) RemoveConsoleSession(c *shipyard.ConsoleSession) error { 806 res, err := r.Table(tblNameConsole).Get(c.ID).Delete().Run(m.session) 807 if err != nil { 808 return err 809 } 810 811 if res.IsNil() { 812 return ErrConsoleSessionDoesNotExist 813 } 814 815 return nil 816 } 817 818 func (m DefaultManager) ConsoleSession(token string) (*shipyard.ConsoleSession, error) { 819 res, err := r.Table(tblNameConsole).Filter(map[string]string{"token": token}).Run(m.session) 820 if err != nil { 821 return nil, err 822 } 823 824 if res.IsNil() { 825 return nil, ErrConsoleSessionDoesNotExist 826 } 827 828 var c *shipyard.ConsoleSession 829 if err := res.One(&c); err != nil { 830 return nil, err 831 } 832 833 return c, nil 834 } 835 836 func (m DefaultManager) ValidateConsoleSessionToken(containerId string, token string) bool { 837 cs, err := m.ConsoleSession(token) 838 if err != nil { 839 log.Errorf("error validating console session token: %s", err) 840 return false 841 } 842 843 if cs == nil || cs.ContainerID != containerId { 844 log.Warnf("unauthorized token request: %s", token) 845 return false 846 } 847 848 if err := m.RemoveConsoleSession(cs); err != nil { 849 log.Error(err) 850 return false 851 } 852 853 return true 854 }