remove obsolete codes from apigateway

This commit is contained in:
Qiu Jian
2020-07-04 13:49:39 +08:00
parent 1d5235dcdc
commit 27b3fb5d52
4 changed files with 0 additions and 313 deletions
-192
View File
@@ -15,207 +15,15 @@
package clientman
import (
"fmt"
"io/ioutil"
"strings"
"time"
"github.com/golang-plus/uuid"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/apigateway/options"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/seclib2"
)
func authVersion() string {
pos := strings.LastIndexByte(options.Options.AuthURL, '/')
if pos > 0 {
return options.Options.AuthURL[pos+1:]
} else {
return ""
}
}
/*
mapTokenManagerV2 在mapTokenManager的基础上增加了 token持久化.后端为sqlite
token存储了两份:分别位于缓存和后端sqlite.
save同时会从sqlite中清理过期的缓存
*/
type ITokenManagerV2 interface {
mcclient.TokenManager
ITotpManager
}
type credential struct {
Token mcclient.TokenCredential
Totp ITotp // 双因子认证。只有options totp enable的情况下该字段才有意义
}
type SMapTokenManagerV2 struct {
table map[string]*credential
}
func UnmarshalV2Token(rbody jsonutils.JSONObject) (cred mcclient.TokenCredential, err error) {
access, err := rbody.Get("access")
if err == nil {
cred = &mcclient.TokenCredentialV2{}
err = access.Unmarshal(cred)
if err != nil {
err = fmt.Errorf("Invalid response when unmarshal V2 Token: %s", err)
}
return
}
err = fmt.Errorf("Invalid response: no access object")
return
}
func UnmarshalV3Token(rbody jsonutils.JSONObject, tokenId string) (cred mcclient.TokenCredential, err error) {
cred = &mcclient.TokenCredentialV3{Id: tokenId}
err = rbody.Unmarshal(cred)
if err != nil {
err = fmt.Errorf("Invalid response when unmarshal V3 Token: %v", err)
}
return
}
func (this *SMapTokenManagerV2) save(token mcclient.TokenCredential) string {
key, e := uuid.NewV4()
if e != nil {
log.Fatalf("uuid.NewV4 returns error!")
}
var totp ITotp
kkey := key.String()
totp = &STotp{}
this.table[kkey] = &credential{Token: token, Totp: totp}
// 存储到后端服务
go func() {
t := jsonutils.Marshal(token).String()
t2 := jsonutils.Marshal(totp).String()
tr := TokenRecord{
TokenID: kkey,
Token: t,
TokenStr: token.GetTokenString(),
Totp: t2,
Version: authVersion(),
ExpireAt: token.GetExpires(),
}
if DB.Create(&tr); DB.Error != nil {
log.Errorf("%v", DB.Error)
} else {
// 删除已经过期的token避免无效token堆积
now := time.Now()
if DB.Delete(TokenRecord{}, "expire_at < ?", now); DB.Error != nil {
log.Errorf("%v", DB.Error)
}
}
}()
return kkey
}
func (this *SMapTokenManagerV2) get(tid string) mcclient.TokenCredential {
if cred := this.table[tid]; cred != nil && cred.Token != nil {
return cred.Token
}
// load from db
err := this.loadFromDB(tid)
if err != nil {
log.Errorf("loadFromDB by tid %s: %v", tid, err)
return nil
} else {
return this.table[tid].Token
}
}
func (this *SMapTokenManagerV2) remove(tid string) {
delete(this.table, tid)
if DB.Delete(TokenRecord{}, "token_id = ?", tid); DB.Error != nil {
log.Errorf("%v", DB.Error)
}
}
func (this *SMapTokenManagerV2) getTotp(tid string) ITotp {
if cred := this.table[tid]; cred != nil && cred.Totp != nil {
return cred.Totp
}
// load from db
err := this.loadFromDB(tid)
if err != nil {
log.Errorf(err.Error())
return nil
} else {
return this.table[tid].Totp
}
}
func (this *SMapTokenManagerV2) saveTotp(tid string) {
totp := this.table[tid].Totp
if totp == nil {
log.Errorf("%s totp is nil", tid)
return
}
// 存储到后端服务
go func() {
tr := TokenRecord{}
if DB.Where("token_id = ?", tid).First(&tr); DB.Error != nil {
log.Errorf("%v", DB.Error)
} else {
DB.Model(&tr).Update("Totp", jsonutils.Marshal(totp).String())
}
}()
}
func (this *SMapTokenManagerV2) loadFromDB(tid string) error {
// load from db
tr := TokenRecord{}
if DB.Where("token_id = ?", tid).First(&tr); DB.Error != nil {
return fmt.Errorf("%v", DB.Error)
}
tjson, err := jsonutils.ParseString(tr.Token)
if err != nil {
return errors.Wrapf(err, "parse token to json: %s", tr.Token)
}
var token mcclient.TokenCredential
if authVersion() == "v3" {
if token, err = UnmarshalV3Token(tjson, tr.TokenStr); err != nil {
return err
}
} else {
if token, err = UnmarshalV2Token(tjson); err != nil {
return err
}
}
var totp STotp
totpJson, err := jsonutils.ParseString(tr.Totp)
if err != nil {
return err
}
if err := totpJson.Unmarshal(&totp); err != nil {
return err
}
this.table[tid] = &credential{Token: token, Totp: &totp}
return nil
}
/*func NewMapTokenManagerV2() ITokenManagerV2 {
return &SMapTokenManagerV2{table: make(map[string]*credential)}
}*/
func InitClient() error {
info := auth.NewAuthInfo(options.Options.AuthURL,
options.Options.AdminDomain,
-52
View File
@@ -1,52 +0,0 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package clientman
import (
"time"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/pkg/errors"
"yunion.io/x/log"
)
var DB *gorm.DB
type TokenRecord struct {
ID uint `gorm:"primary_key"`
TokenID string `gorm:"not null;unique"`
Token string `gorm:"not null;unique"`
TokenStr string `gorm:"not null;DEFAULT:''"`
Totp string `gorm:"not null;DEFAULT:''"`
Version string `gorm:"not null;DEFAULT:'v2'"`
ExpireAt time.Time
}
func initDB(dialect string, args ...interface{}) error {
if DB == nil {
db, err := gorm.Open(dialect, args...)
if err != nil {
return errors.Wrapf(err, "Init DB by args: %v", args)
}
// Migrate the schema
db.AutoMigrate(&TokenRecord{})
DB = db
return nil
}
log.Warningf("DB: %s , Conn: %v already connected...", dialect, args)
return nil
}
-67
View File
@@ -16,10 +16,6 @@ package clientman
import (
"encoding/base32"
"fmt"
"time"
"github.com/pquerna/otp/totp"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
@@ -27,69 +23,6 @@ import (
const MAX_OTP_RETRY = 5 // totp验证最大重试次数
type ITotp interface {
UpdateRetryCount()
IsVerified() bool
MarkVerified()
VerifyTotpPasscode(s *mcclient.ClientSession, uid, passcode string) error
}
type ITotpManager interface {
GetTotp(tid string) ITotp
SaveTotp(tid string)
}
type STotp struct {
RetryCount int `json:"retry_count"` // 重试计数器
LockExpireTime time.Time `json:"lock_expire_time"` // 锁定时间
Verified bool `json:"verified"` // 验证状态
}
func (self *STotp) UpdateRetryCount() {
if self.RetryCount < MAX_OTP_RETRY {
self.RetryCount += 1
// 锁定
if self.RetryCount >= MAX_OTP_RETRY {
self.LockExpireTime = time.Now().Add(30 * time.Second)
}
} else {
// 清零计数器,解除锁定
if self.LockExpireTime.Before(time.Now()) {
self.LockExpireTime = time.Now()
self.RetryCount = 0
}
}
}
func (self *STotp) IsVerified() bool {
return self.Verified
}
func (self *STotp) MarkVerified() {
self.Verified = true
}
func (self *STotp) VerifyTotpPasscode(s *mcclient.ClientSession, uid, passcode string) error {
secret, err := fetchUserTotpCredSecret(s, uid)
if err != nil {
return fmt.Errorf("fetch totp secrets error: %s", err.Error())
}
releaseSeconds := self.LockExpireTime.Unix() - time.Now().Unix()
if releaseSeconds > 0 {
return fmt.Errorf("locked, retry after %d seconds", releaseSeconds)
}
if totp.Validate(passcode, secret) {
self.MarkVerified()
return nil
}
self.UpdateRetryCount()
return fmt.Errorf("invalid passcode")
}
// 获取用户TOTP credential 密码.
func fetchUserTotpCredSecret(s *mcclient.ClientSession, uid string) (string, error) {
secret, err := modules.Credentials.GetTotpSecret(s, uid)
-2
View File
@@ -28,8 +28,6 @@ type GatewayOptions struct {
EnableTotp bool `help:"Enable two-factor authentication" default:"true"`
// SqlitePath string `help:"sqlite db path" default:"/etc/yunion/data/yunionapi.db"`
common_options.CommonOptions `"request_worker_count->default":"32"`
}