etcd許可權系統認證過程加cache
阿新 • • 發佈:2019-01-02
最近在研究etcd的許可權機制,etcd用的認證方式比較簡單basic auth。原理也比較簡單易懂,但輕率上線後,發現一個大坑,就是認證時候用來比較密碼的雜湊是bcript,而且是每個請求都會調。這個耗時很大,導致叢集效能下降的厲害,基本不能用了。
查遍官方文件,說3.1+ 用https common name的方式可以解決這個問題,但是我就不想上https,涉及改造的工作量有點大,就想通過auth簡單的把誤操作的行為隔離一下。
於是乎只能開始動手改了,簡單的加一個cache先用。
首先我們用的etcd版本為2.1.1
git clone https://github.com/coreos/etcd.git
git checkout v2.1.1
下載程式碼後,切換到 v2.1.1 tag下
開啟目錄 etcdserver
在目錄下新增新檔案,姑且叫做 password_map.go
新增如下程式碼
?
// author:ZeaLoVe
// password map of etcd v2 api
package auth
import (
"fmt"
"sync"
)
// key : string meke by hashed password + plaintext password
// value: error the result of CompareHashAndPassword type PasswordMap struct {
sync.RWMutex
M map[string]error
}
var DefaultPasswdMap = PasswordMap{
M: make(map[string]error),
}
func (this *PasswordMap) Hit(hashed, pt string) bool {
this.RLock()
defer this.RUnlock()
if _, ok := this.M[hashed+pt]; ok {
return ok
}
return false
}
// Get must called after Hit func (this *PasswordMap) Get(hashed, pt string) error {
this.RLock()
defer this.RUnlock()
if val, ok := this.M[hashed+pt]; ok {
return val
}
return fmt.Errorf("no hit")
}
func (this *PasswordMap) Set(hashed string, pt string, err error) {
if hashed == "" {
return
}
this.Lock()
defer this.Unlock()
this.M[hashed+pt] = err
}
|
開啟該資料夾下的auth.go 找到 CheckPassword函式
修改為
?
func (u User) CheckPassword(password string) bool {
if DefaultPasswdMap.Hit(u.Password, password) {
return DefaultPasswdMap.Get(u.Password, password) == nil
}
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
DefaultPasswdMap.Set(u.Password, password, err)
return err == nil
}
|
對於其他版本,雖然實現上可能有些區別,但整個原理是一樣的(我看過3.1的基本沒怎麼改變)。此改造不會影響第一次請求的耗時,但後面不會對相同的密碼再次呼叫bcript,會直接返回快取的結果,極大提高了效能
但該實現沒有回收快取的空間,所以如果有人對同一個賬號用各種不同的密碼輪番攻擊,可能會導致記憶體持續上升。但經過壓測,發現即使試十萬次記憶體也只上漲不到30M。可以暫時忽略這個問題。
即使記憶體大到一定程度,重啟也可以恢復。