Skip to content

Commit

Permalink
支持配置加密功能
Browse files Browse the repository at this point in the history
  • Loading branch information
raywlwang committed May 15, 2023
1 parent 3c9f7c5 commit 3f8df56
Show file tree
Hide file tree
Showing 33 changed files with 1,534 additions and 28 deletions.
33 changes: 32 additions & 1 deletion cache/config_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ type Entry struct {
Content string
Md5 string
Version uint64
DataKey string
// 创建的时候,设置过期时间
ExpireTime time.Time
// 标识是否是空缓存
Expand Down Expand Up @@ -239,7 +240,7 @@ func (fc *fileCache) GetOrLoadIfAbsent(namespace, group, fileName string) (*Entr
// 从数据库中加载数据
atomic.AddInt32(&fc.loadCnt, 1)

file, err := fc.storage.GetConfigFileRelease(nil, namespace, group, fileName)
file, dataKey, err := fc.getConfigFileReleaseAndDataKey(namespace, group, fileName)
if err != nil {
configLog.Error("[Config][Cache] load config file release error.",
zap.String("namespace", namespace),
Expand Down Expand Up @@ -269,6 +270,7 @@ func (fc *fileCache) GetOrLoadIfAbsent(namespace, group, fileName string) (*Entr
Content: file.Content,
Md5: file.Md5,
Version: file.Version,
DataKey: dataKey,
ExpireTime: fc.getExpireTime(),
}

Expand All @@ -287,6 +289,35 @@ func (fc *fileCache) GetOrLoadIfAbsent(namespace, group, fileName string) (*Entr
return newEntry, nil
}

func (fc *fileCache) getConfigFileReleaseAndDataKey(
namespace, group, fileName string) (*model.ConfigFileRelease, string, error) {
file, err := fc.storage.GetConfigFileRelease(nil, namespace, group, fileName)
if err != nil {
configLog.Error("[Config][Cache] load config file release error.",
zap.String("namespace", namespace),
zap.String("group", group),
zap.String("fileName", fileName),
zap.Error(err))
return nil, "", err
}
tags, err := fc.storage.QueryTagByConfigFile(namespace, group, fileName)
if err != nil {
configLog.Error("[Config][Cache] load config file tag error.",
zap.String("namespace", namespace),
zap.String("group", group),
zap.String("fileName", fileName),
zap.Error(err))
return nil, "", err
}
var dataKey string
for _, tag := range tags {
if tag.Key == utils.ConfigFileTagKeyDataKey {
dataKey = tag.Value
}
}
return file, dataKey, nil
}

// Remove 删除缓存对象
func (fc *fileCache) Remove(namespace, group, fileName string) {
atomic.AddInt32(&fc.removeCnt, 1)
Expand Down
21 changes: 21 additions & 0 deletions cache/config_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ func TestGetAndRemoveAndReloadConfigFile(t *testing.T) {
// Mock 数据
configFile := assembleConfigFile()
configFileRelease := assembleConfigFileRelease(configFile)
configFileTags := assembelConfigFileTags(configFile)

// 前三次调用返回一个值,第四次调用返回另外一个值,默认更新
mockedStorage.EXPECT().GetConfigFileRelease(nil, testNamespace, testGroup, testFile).Return(configFileRelease, nil).Times(3)
mockedStorage.EXPECT().QueryTagByConfigFile(testNamespace, testGroup, testFile).Return(configFileTags, nil).Times(3)

for i := 0; i < 100; i++ {
go func() {
Expand Down Expand Up @@ -93,9 +95,11 @@ func TestConcurrentGetConfigFile(t *testing.T) {
// Mock 数据
configFile := assembleConfigFile()
configFileRelease := assembleConfigFileRelease(configFile)
configFileTags := assembelConfigFileTags(configFile)

// 一共调用三次,
mockedStorage.EXPECT().GetConfigFileRelease(nil, testNamespace, testGroup, testFile).Return(configFileRelease, nil).Times(1)
mockedStorage.EXPECT().QueryTagByConfigFile(testNamespace, testGroup, testFile).Return(configFileTags, nil).Times(1)

for i := 0; i < 1000; i++ {
go func() {
Expand All @@ -121,7 +125,9 @@ func TestUpdateCache(t *testing.T) {
configFileRelease := assembleConfigFileRelease(configFile)
configFileRelease.Content = firstValue
configFileRelease.Version = firstVersion
configFileTags := assembelConfigFileTags(configFile)
first := mockedStorage.EXPECT().GetConfigFileRelease(nil, testNamespace, testGroup, testFile).Return(configFileRelease, nil).Times(1)
mockedStorage.EXPECT().QueryTagByConfigFile(testNamespace, testGroup, testFile).Return(configFileTags, nil).Times(1)

// 第二次调用返会值
secondValue := "secondValue"
Expand All @@ -130,7 +136,9 @@ func TestUpdateCache(t *testing.T) {
configFileRelease2 := assembleConfigFileRelease(configFile2)
configFileRelease2.Content = secondValue
configFileRelease2.Version = secondVersion
configFileTags = assembelConfigFileTags(configFile)
second := mockedStorage.EXPECT().GetConfigFileRelease(nil, testNamespace, testGroup, testFile).Return(configFileRelease2, nil).Times(1)
mockedStorage.EXPECT().QueryTagByConfigFile(testNamespace, testGroup, testFile).Return(configFileTags, nil).Times(1)

gomock.InOrder(first, second)

Expand Down Expand Up @@ -190,6 +198,19 @@ func assembleConfigFileRelease(configFile *model.ConfigFile) *model.ConfigFileRe
}
}

func assembelConfigFileTags(configFile *model.ConfigFile) []*model.ConfigFileTag {
tags := []*model.ConfigFileTag{
{
Key: utils.ConfigFileTagKeyDataKey,
Value: "data key",
Namespace: configFile.Namespace,
Group: configFile.Group,
FileName: configFile.Name,
},
}
return tags
}

func assembleConfigFileGroup() *model.ConfigFileGroup {
return &model.ConfigFileGroup{
Id: uint64(100),
Expand Down
15 changes: 15 additions & 0 deletions common/api/v1/config_file_response_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ func NewConfigFileBatchQueryResponse(
}
}

func NewConfigFileBatchQueryResponseWithMessage(
code apimodel.Code, message string) *apiconfig.ConfigBatchQueryResponse {
return &apiconfig.ConfigBatchQueryResponse{
Code: &wrappers.UInt32Value{Value: uint32(code)},
Info: &wrappers.StringValue{Value: code2info[uint32(code)]},
}
}

func NewConfigFileTemplateResponse(
code apimodel.Code, template *apiconfig.ConfigFileTemplate) *apiconfig.ConfigResponse {
return &apiconfig.ConfigResponse{
Expand Down Expand Up @@ -176,3 +184,10 @@ func NewConfigFileExportResponse(code apimodel.Code, data []byte) *apiconfig.Con
Data: &wrappers.BytesValue{Value: data},
}
}

func NewConfigFileExportResponseWithMessage(code apimodel.Code, message string) *apiconfig.ConfigExportResponse {
return &apiconfig.ConfigExportResponse{
Code: &wrappers.UInt32Value{Value: uint32(code)},
Info: &wrappers.StringValue{Value: code2info[uint32(code)] + ":" + message},
}
}
2 changes: 2 additions & 0 deletions common/utils/config_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const (
ConfigFileImportConflictSkip = "skip"
// ConfigFileImportConflictOverwrite 导入配置文件发生冲突覆盖原配置文件
ConfigFileImportConflictOverwrite = "overwrite"
// TagKeyEncryptConfigEncryptKey 加密密钥 tag key
ConfigFileTagKeyDataKey = "data_key"
)

// GenFileId 生成文件 Id
Expand Down
1 change: 1 addition & 0 deletions config/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/polarismesh/polaris/common/utils"
"github.com/polarismesh/polaris/namespace"
"github.com/polarismesh/polaris/plugin"
_ "github.com/polarismesh/polaris/plugin/configcrypto"
_ "github.com/polarismesh/polaris/plugin/healthchecker/memory"
_ "github.com/polarismesh/polaris/plugin/healthchecker/redis"
_ "github.com/polarismesh/polaris/plugin/history/logger"
Expand Down
47 changes: 43 additions & 4 deletions config/client_config_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package config

import (
"context"
"encoding/base64"

apiconfig "github.com/polarismesh/specification/source/go/api/v1/config_manage"
apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
Expand All @@ -28,6 +29,7 @@ import (
api "github.com/polarismesh/polaris/common/api/v1"
"github.com/polarismesh/polaris/common/utils"
utils2 "github.com/polarismesh/polaris/config/utils"
"github.com/polarismesh/polaris/plugin/configcrypto"
)

type (
Expand All @@ -41,6 +43,7 @@ func (s *Server) GetConfigFileForClient(ctx context.Context,
group := client.GetGroup().GetValue()
fileName := client.GetFileName().GetValue()
clientVersion := client.GetVersion().GetValue()
publicKey := client.GetPublicKey().GetValue()

if namespace == "" || group == "" || fileName == "" {
return api.NewConfigClientResponseWithMessage(
Expand All @@ -50,8 +53,11 @@ func (s *Server) GetConfigFileForClient(ctx context.Context,
requestID := utils.ParseRequestID(ctx)

log.Info("[Config][Service] load config file from cache.",
zap.String("requestId", requestID), zap.String("namespace", namespace),
zap.String("group", group), zap.String("file", fileName))
zap.String("requestId", requestID),
zap.String("namespace", namespace),
zap.String("group", group),
zap.String("file", fileName),
zap.String("publicKey", publicKey))

// 从缓存中获取配置内容
entry, err := s.fileCache.GetOrLoadIfAbsent(namespace, group, fileName)
Expand Down Expand Up @@ -88,7 +94,40 @@ func (s *Server) GetConfigFileForClient(ctx context.Context,
zap.String("file", fileName),
zap.Uint64("version", entry.Version))

resp := utils2.GenConfigFileResponse(namespace, group, fileName, entry.Content, entry.Md5, entry.Version)
// 加密配置返回用公钥加密的数据密钥
if entry.DataKey != "" && publicKey != "" {
dataKeyBytes, err := base64.StdEncoding.DecodeString(entry.DataKey)
if err != nil {
log.Error("[Config][Service] base64 decode data key error.",
zap.String("requestId", requestID),
zap.String("dataKey", entry.DataKey),
zap.Error(err))
}
cipherDataKey, err := configcrypto.EncryptToBase64(dataKeyBytes, publicKey)
if err != nil {
log.Error("[Config][Service] rsa encrypt data key error.",
zap.String("requestId", requestID),
zap.String("dataKey", entry.DataKey),
zap.Error(err))
}
resp := utils2.GenConfigFileResponse(namespace, group, fileName,
entry.Content, entry.Md5, entry.Version, true, cipherDataKey)
log.Info("[Config][Client] client get config file resp.",
zap.String("requestId", requestID),
zap.String("file", resp.GetConfigFile().GetFileName().GetValue()),
zap.String("dataKey", resp.GetConfigFile().GetDataKey().GetValue()),
zap.Bool("isEncrypted", resp.GetConfigFile().GetIsEncrypted().GetValue()))
return resp
}
isEntrypted := entry.DataKey != ""
resp := utils2.GenConfigFileResponse(namespace, group, fileName,
entry.Content, entry.Md5, entry.Version, isEntrypted, "")

log.Info("[Config][Client] client get config file resp.",
zap.String("requestId", requestID),
zap.String("file", resp.GetConfigFile().GetFileName().GetValue()),
zap.String("dataKey", resp.GetConfigFile().GetDataKey().GetValue()),
zap.Bool("isEncrypted", resp.GetConfigFile().GetIsEncrypted().GetValue()))
return resp
}

Expand Down Expand Up @@ -151,7 +190,7 @@ func (s *Server) doCheckClientConfigFile(ctx context.Context, configFiles []*api
}

if compartor(configFile, entry) {
return utils2.GenConfigFileResponse(namespace, group, fileName, "", entry.Md5, entry.Version)
return utils2.GenConfigFileResponse(namespace, group, fileName, "", entry.Md5, entry.Version, false, "")
}
}

Expand Down
Loading

0 comments on commit 3f8df56

Please sign in to comment.