Files
waf-platform/EdgeDNS/internal/nodes/manager_key.go
2026-03-22 17:37:40 +08:00

290 lines
5.9 KiB
Go

// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package nodes
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeDNS/internal/dbs"
"github.com/TeaOSLab/EdgeDNS/internal/models"
"github.com/TeaOSLab/EdgeDNS/internal/remotelogs"
"github.com/TeaOSLab/EdgeDNS/internal/rpc"
"sync"
"time"
)
// KeyManager 密钥管理器
type KeyManager struct {
domainKeyMap map[int64]*models.NSKeys // domainId => *NSKeys
zoneKeyMap map[int64]*models.NSKeys // zoneId => *NSKeys
db *dbs.DB
locker sync.RWMutex
version int64
notifier chan bool
readyCh chan struct{} // 初始加载完成后关闭
}
// NewKeyManager 获取密钥管理器
func NewKeyManager(db *dbs.DB) *KeyManager {
return &KeyManager{
domainKeyMap: map[int64]*models.NSKeys{},
zoneKeyMap: map[int64]*models.NSKeys{},
db: db,
notifier: make(chan bool, 8),
readyCh: make(chan struct{}),
}
}
// Start 启动自动任务
func (this *KeyManager) Start() {
remotelogs.Println("KEY_MANAGER", "starting ...")
// 从本地数据库中加载数据
err := this.Load()
if err != nil {
if rpc.IsConnError(err) {
remotelogs.Debug("KEY_MANAGER", "load failed: "+err.Error())
} else {
remotelogs.Error("KEY_MANAGER", "load failed: "+err.Error())
}
}
// 初始化运行
err = this.LoopAll()
if err != nil {
if rpc.IsConnError(err) {
remotelogs.Debug("KEY_MANAGER", "loop failed: "+err.Error())
} else {
remotelogs.Error("KEY_MANAGER", "loop failed: "+err.Error())
}
}
// 通知初始加载完成
close(this.readyCh)
// 更新
var ticker = time.NewTicker(1 * time.Minute)
for {
select {
case <-ticker.C:
case <-this.notifier:
}
err := this.LoopAll()
if err != nil {
if rpc.IsConnError(err) {
remotelogs.Debug("KEY_MANAGER", "loop failed: "+err.Error())
} else {
remotelogs.Error("KEY_MANAGER", "loop failed: "+err.Error())
}
}
}
}
// Load 从数据库中加载数据
func (this *KeyManager) Load() error {
var offset = 0
var size = 10000
for {
keys, err := this.db.ListKeys(offset, size)
if err != nil {
return err
}
if len(keys) == 0 {
break
}
this.locker.Lock()
for _, key := range keys {
if key.ZoneId > 0 {
keyList, ok := this.zoneKeyMap[key.ZoneId]
if ok {
keyList.Add(key)
} else {
keyList = models.NewNSKeys()
keyList.Add(key)
this.zoneKeyMap[key.ZoneId] = keyList
}
} else if key.DomainId > 0 {
keyList, ok := this.domainKeyMap[key.DomainId]
if ok {
keyList.Add(key)
} else {
keyList = models.NewNSKeys()
keyList.Add(key)
this.domainKeyMap[key.DomainId] = keyList
}
}
if key.Version > this.version {
this.version = key.Version
}
}
this.locker.Unlock()
offset += size
}
if this.version > 0 {
this.version++
}
return nil
}
func (this *KeyManager) LoopAll() error {
for {
hasNext, err := this.Loop()
if err != nil {
return err
}
if !hasNext {
break
}
}
return nil
}
// Loop 单次循环任务
func (this *KeyManager) Loop() (hasNext bool, err error) {
client, err := rpc.SharedRPC()
if err != nil {
return false, err
}
resp, err := client.NSKeyRPC.ListNSKeysAfterVersion(client.Context(), &pb.ListNSKeysAfterVersionRequest{
Version: this.version,
Size: 20000,
})
if err != nil {
return false, err
}
var keys = resp.NsKeys
if len(keys) == 0 {
return false, nil
}
for _, key := range keys {
this.processKey(key)
if key.Version > this.version {
this.version = key.Version
}
}
this.version++
return true, nil
}
func (this *KeyManager) FindKeysWithDomain(domainId int64) []*models.NSKey {
this.locker.RLock()
defer this.locker.RUnlock()
keys, ok := this.domainKeyMap[domainId]
if ok {
return keys.All()
}
return nil
}
// NotifyUpdate 通知更新
func (this *KeyManager) NotifyUpdate() {
select {
case this.notifier <- true:
default:
}
}
// 处理Key
func (this *KeyManager) processKey(key *pb.NSKey) {
if key.NsDomain == nil && key.NsZone == nil {
return
}
if !key.IsOn || key.IsDeleted {
this.locker.Lock()
if key.NsDomain != nil {
list, ok := this.domainKeyMap[key.NsDomain.Id]
if ok {
list.Remove(key.Id)
}
}
if key.NsZone != nil {
list, ok := this.zoneKeyMap[key.NsZone.Id]
if ok {
list.Remove(key.Id)
}
}
this.locker.Unlock()
// 从数据库中删除
if this.db != nil {
err := this.db.DeleteKey(key.Id)
if err != nil {
remotelogs.Error("KEY_MANAGER", "delete key from db failed: "+err.Error())
}
}
return
}
var domainId int64
var zoneId int64
if key.NsDomain != nil {
domainId = key.NsDomain.Id
}
if key.NsZone != nil {
zoneId = key.NsZone.Id
}
// 存入数据库
if this.db != nil {
exists, err := this.db.ExistsKey(key.Id)
if err != nil {
remotelogs.Error("KEY_MANAGER", "query failed: "+err.Error())
} else {
if exists {
err = this.db.UpdateKey(key.Id, domainId, zoneId, key.Algo, key.Secret, key.SecretType, key.Version)
if err != nil {
remotelogs.Error("KEY_MANAGER", "update failed: "+err.Error())
}
} else {
err = this.db.InsertKey(key.Id, domainId, zoneId, key.Algo, key.Secret, key.SecretType, key.Version)
if err != nil {
remotelogs.Error("KEY_MANAGER", "insert failed: "+err.Error())
}
}
}
}
// 加入缓存Map
this.locker.Lock()
var nsKey = &models.NSKey{
Id: key.Id,
DomainId: domainId,
ZoneId: zoneId,
Algo: key.Algo,
Secret: key.Secret,
SecretType: key.SecretType,
Version: key.Version,
}
if zoneId > 0 {
keyList, ok := this.zoneKeyMap[zoneId]
if ok {
keyList.Add(nsKey)
} else {
keyList = models.NewNSKeys()
keyList.Add(nsKey)
this.zoneKeyMap[zoneId] = keyList
}
} else if domainId > 0 {
keyList, ok := this.domainKeyMap[domainId]
if ok {
keyList.Add(nsKey)
} else {
keyList = models.NewNSKeys()
keyList.Add(nsKey)
this.domainKeyMap[domainId] = keyList
}
}
this.locker.Unlock()
}