Skip to content

Commit

Permalink
配置加密功能支持阿里云KMS RAM 访问方式 (#788)
Browse files Browse the repository at this point in the history
* support aliyun kms ram mode
  • Loading branch information
Sunrisea authored Jan 21, 2025
1 parent 25436c0 commit 7c3b1dc
Show file tree
Hide file tree
Showing 8 changed files with 319 additions and 41 deletions.
6 changes: 6 additions & 0 deletions common/constant/client_config_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ func WithKMSv3Config(kmsv3Config *KMSv3Config) ClientOption {
}
}

func WithKMSConfig(kmsConfig *KMSConfig) ClientOption {
return func(config *ClientConfig) {
config.KMSConfig = kmsConfig
}
}

// WithCacheDir ...
func WithCacheDir(cacheDir string) ClientOption {
return func(config *ClientConfig) {
Expand Down
33 changes: 20 additions & 13 deletions common/constant/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,20 @@ type ServerConfig struct {
}

type ClientConfig struct {
TimeoutMs uint64 // timeout for requesting Nacos server, default value is 10000ms
ListenInterval uint64 // Deprecated
BeatInterval int64 // the time interval for sending beat to server,default value is 5000ms
NamespaceId string // the namespaceId of Nacos.When namespace is public, fill in the blank string here.
AppName string // the appName
AppKey string // the client identity information
Endpoint string // the endpoint for get Nacos server addresses
RegionId string // the regionId for kms
AccessKey string // the AccessKey for kms
SecretKey string // the SecretKey for kms
OpenKMS bool // it's to open kms, default is false. https://help.aliyun.com/product/28933.html
KMSVersion KMSVersion // kms client version. https://help.aliyun.com/document_detail/380927.html
KMSv3Config *KMSv3Config //KMSv3 configuration. https://help.aliyun.com/document_detail/601596.html
TimeoutMs uint64 // timeout for requesting Nacos server, default value is 10000ms
ListenInterval uint64 // Deprecated
BeatInterval int64 // the time interval for sending beat to server,default value is 5000ms
NamespaceId string // the namespaceId of Nacos.When namespace is public, fill in the blank string here.
AppName string // the appName
AppKey string // the client identity information
Endpoint string // the endpoint for get Nacos server addresses
RegionId string // the regionId for kms
AccessKey string // the AccessKey for kms
SecretKey string // the SecretKey for kms
OpenKMS bool // it's to open kms, default is false. https://help.aliyun.com/product/28933.html
KMSVersion KMSVersion // kms client version. https://help.aliyun.com/document_detail/380927.html
KMSv3Config *KMSv3Config //KMSv3 configuration. https://help.aliyun.com/document_detail/601596.html
KMSConfig *KMSConfig
CacheDir string // the directory for persist nacos service info,default value is current path
DisableUseSnapShot bool // It's a switch, default is false, means that when get remote config fail, use local cache file instead
UpdateThreadNum int // the number of goroutine for update nacos service info,default value is 20
Expand Down Expand Up @@ -110,3 +111,9 @@ type KMSv3Config struct {
Endpoint string
CaContent string
}

type KMSConfig struct {
Endpoint string
OpenSSL string
CaContent string
}
1 change: 1 addition & 0 deletions common/encryption/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,5 @@ var (
EmptyPasswordKmsV3ClientInitError = fmt.Errorf("init kmsV3 client failed with empty password")
EmptyClientKeyContentKmsV3ClientInitError = fmt.Errorf("init kmsV3 client failed with empty client key content")
EmptyCaVerifyKmsV3ClientInitError = fmt.Errorf("init kmsV3 client failed with empty ca verify")
EmptyEndpointKmsRamClientInitError = fmt.Errorf("init kmsRam client failed with empty endpoint")
)
17 changes: 12 additions & 5 deletions common/encryption/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ func newKmsHandler() *KmsHandler {

func RegisterConfigEncryptionKmsPlugins(encryptionHandler Handler, clientConfig constant.ClientConfig) {
innerKmsClient, err := innerNewKmsClient(clientConfig)
if err == nil && innerKmsClient == nil {
if innerKmsClient == nil {
err = errors.New("create kms client failed.")
}
if err != nil && innerKmsClient == nil {
err = errors.New("create kms client failed.")
}
if err != nil {
Expand Down Expand Up @@ -191,10 +194,10 @@ func (d *KmsHandler) contentParamCheck(content string) error {
return nil
}

func innerNewKmsClient(clientConfig constant.ClientConfig) (kmsClient *KmsClient, err error) {
func innerNewKmsClient(clientConfig constant.ClientConfig) (kmsClient KmsClient, err error) {
switch clientConfig.KMSVersion {
case constant.KMSv1, constant.DEFAULT_KMS_VERSION:
kmsClient, err = newKmsV1Client(clientConfig)
kmsClient, err = newKmsRamClient(clientConfig)
case constant.KMSv3:
kmsClient, err = newKmsV3Client(clientConfig)
default:
Expand All @@ -203,15 +206,19 @@ func innerNewKmsClient(clientConfig constant.ClientConfig) (kmsClient *KmsClient
return kmsClient, err
}

func newKmsV1Client(clientConfig constant.ClientConfig) (*KmsClient, error) {
func newKmsV1Client(clientConfig constant.ClientConfig) (KmsClient, error) {
return NewKmsV1ClientWithAccessKey(clientConfig.RegionId, clientConfig.AccessKey, clientConfig.SecretKey)
}

func newKmsV3Client(clientConfig constant.ClientConfig) (*KmsClient, error) {
func newKmsV3Client(clientConfig constant.ClientConfig) (KmsClient, error) {
return NewKmsV3ClientWithConfig(&dkms_api.Config{
Protocol: tea.String("https"),
Endpoint: tea.String(clientConfig.KMSv3Config.Endpoint),
ClientKeyContent: tea.String(clientConfig.KMSv3Config.ClientKeyContent),
Password: tea.String(clientConfig.KMSv3Config.Password),
}, clientConfig.KMSv3Config.CaContent)
}

func newKmsRamClient(clientConfig constant.ClientConfig) (KmsClient, error) {
return NewKmsRamClient(clientConfig.KMSConfig, clientConfig.RegionId, clientConfig.AccessKey, clientConfig.SecretKey)
}
154 changes: 142 additions & 12 deletions common/encryption/kms_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ package encryption

import (
"fmt"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
kms20160120 "github.com/alibabacloud-go/kms-20160120/v3/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
"github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
dkms_api "github.com/aliyun/alibabacloud-dkms-gcs-go-sdk/openapi"
dkms_transfer "github.com/aliyun/alibabacloud-dkms-transfer-go-sdk/sdk"
Expand All @@ -28,12 +32,20 @@ import (
"strings"
)

type KmsClient struct {
type KmsClient interface {
Decrypt(cipherContent string) (string, error)
Encrypt(content string, keyId string) (string, error)
GenerateDataKey(keyId, keySpec string) (string, string, error)
GetKmsVersion() constant.KMSVersion
setKmsVersion(constant.KMSVersion)
}

type TransferKmsClient struct {
*dkms_transfer.KmsTransferClient
kmsVersion constant.KMSVersion
}

func NewKmsV1ClientWithAccessKey(regionId, ak, sk string) (*KmsClient, error) {
func NewKmsV1ClientWithAccessKey(regionId, ak, sk string) (*TransferKmsClient, error) {
var rErr error
if rErr = checkKmsV1InitParam(regionId, ak, sk); rErr != nil {
return nil, rErr
Expand All @@ -60,7 +72,20 @@ func checkKmsV1InitParam(regionId, ak, sk string) error {
return nil
}

func NewKmsV3ClientWithConfig(config *dkms_api.Config, caVerify string) (*KmsClient, error) {
func checkKmsRamInitParam(endpoint, ak, sk string) error {
if len(endpoint) == 0 {
return EmptyEndpointKmsRamClientInitError
}
if len(ak) == 0 {
return EmptyAkKmsV1ClientInitError
}
if len(sk) == 0 {
return EmptySkKmsV1ClientInitError
}
return nil
}

func NewKmsV3ClientWithConfig(config *dkms_api.Config, caVerify string) (*TransferKmsClient, error) {
var rErr error
if rErr = checkKmsV3InitParam(config, caVerify); rErr != nil {
return nil, rErr
Expand Down Expand Up @@ -96,39 +121,39 @@ func checkKmsV3InitParam(config *dkms_api.Config, caVerify string) error {
return nil
}

func newKmsV1ClientWithAccessKey(regionId, ak, sk string) (*KmsClient, error) {
func newKmsV1ClientWithAccessKey(regionId, ak, sk string) (*TransferKmsClient, error) {
logger.Debugf("init kms client with region:[%s], ak:[%s]xxx, sk:[%s]xxx\n",
regionId, ak[:len(ak)/maskUnit8Width], sk[:len(sk)/maskUnit8Width])
return newKmsClient(regionId, ak, sk, nil)
}

func newKmsV3ClientWithConfig(config *dkms_api.Config) (*KmsClient, error) {
func newKmsV3ClientWithConfig(config *dkms_api.Config) (*TransferKmsClient, error) {
logger.Debugf("init kms client with endpoint:[%s], clientKeyContent:[%s], password:[%s]\n",
config.Endpoint, (*config.ClientKeyContent)[:len(*config.ClientKeyContent)/maskUnit8Width],
(*config.Password)[:len(*config.Password)/maskUnit8Width])
return newKmsClient("", "", "", config)
}

func newKmsClient(regionId, ak, sk string, config *dkms_api.Config) (*KmsClient, error) {
func newKmsClient(regionId, ak, sk string, config *dkms_api.Config) (*TransferKmsClient, error) {
client, err := dkms_transfer.NewClientWithAccessKey(regionId, ak, sk, config)
if err != nil {
return nil, err
}
return &KmsClient{
return &TransferKmsClient{
KmsTransferClient: client,
}, nil
}

func (kmsClient *KmsClient) GetKmsVersion() constant.KMSVersion {
func (kmsClient *TransferKmsClient) GetKmsVersion() constant.KMSVersion {
return kmsClient.kmsVersion
}

func (kmsClient *KmsClient) setKmsVersion(kmsVersion constant.KMSVersion) {
func (kmsClient *TransferKmsClient) setKmsVersion(kmsVersion constant.KMSVersion) {
logger.Debug("successfully set kms client version to " + kmsVersion)
kmsClient.kmsVersion = kmsVersion
}

func (kmsClient *KmsClient) GenerateDataKey(keyId, keySpec string) (string, string, error) {
func (kmsClient *TransferKmsClient) GenerateDataKey(keyId, keySpec string) (string, string, error) {
generateDataKeyRequest := kms.CreateGenerateDataKeyRequest()
generateDataKeyRequest.Scheme = kmsScheme
generateDataKeyRequest.AcceptFormat = kmsAcceptFormat
Expand All @@ -141,7 +166,7 @@ func (kmsClient *KmsClient) GenerateDataKey(keyId, keySpec string) (string, stri
return generateDataKeyResponse.Plaintext, generateDataKeyResponse.CiphertextBlob, nil
}

func (kmsClient *KmsClient) Decrypt(cipherContent string) (string, error) {
func (kmsClient *TransferKmsClient) Decrypt(cipherContent string) (string, error) {
request := kms.CreateDecryptRequest()
request.Method = http.MethodPost
request.Scheme = kmsScheme
Expand All @@ -154,7 +179,7 @@ func (kmsClient *KmsClient) Decrypt(cipherContent string) (string, error) {
return response.Plaintext, nil
}

func (kmsClient *KmsClient) Encrypt(content, keyId string) (string, error) {
func (kmsClient *TransferKmsClient) Encrypt(content, keyId string) (string, error) {
request := kms.CreateEncryptRequest()
request.Method = http.MethodPost
request.Scheme = kmsScheme
Expand All @@ -171,3 +196,108 @@ func (kmsClient *KmsClient) Encrypt(content, keyId string) (string, error) {
func GetDefaultKMSv1KeyId() string {
return constant.MSE_KMSv1_DEFAULT_KEY_ID
}

type RamKmsClient struct {
*kms20160120.Client
kmsVersion constant.KMSVersion
runtime *util.RuntimeOptions
}

func NewKmsRamClient(kmsConfig *constant.KMSConfig, regionId, ak, sk string) (*RamKmsClient, error) {
if kmsConfig == nil || len(kmsConfig.Endpoint) == 0 {
if err := checkKmsV1InitParam(regionId, ak, sk); err != nil {
return nil, err
}
KmsV1Config := &openapi.Config{}
KmsV1Config.AccessKeyId = tea.String(ak)
KmsV1Config.AccessKeySecret = tea.String(sk)
KmsV1Config.RegionId = tea.String(regionId)
_result, _err := kms20160120.NewClient(KmsV1Config)
if _err != nil {
return nil, _err
}
_ramClient := &RamKmsClient{
Client: _result,
kmsVersion: constant.KMSv1,
runtime: &util.RuntimeOptions{},
}
return _ramClient, nil
}
if err := checkKmsRamInitParam(kmsConfig.Endpoint, ak, sk); err != nil {
return nil, err
}
config := &openapi.Config{}
config.AccessKeyId = tea.String(ak)
config.AccessKeySecret = tea.String(sk)
if len(regionId) != 0 {
config.RegionId = tea.String(regionId)
}
config.Endpoint = tea.String(kmsConfig.Endpoint)
config.Ca = tea.String(kmsConfig.CaContent)
runtimeOption := &util.RuntimeOptions{}
if len(kmsConfig.CaContent) == 0 {
runtimeOption.IgnoreSSL = tea.Bool(true)
}
if kmsConfig.OpenSSL == "true" {
runtimeOption.IgnoreSSL = tea.Bool(false)
} else if kmsConfig.OpenSSL == "false" {
runtimeOption.IgnoreSSL = tea.Bool(true)
}
_result, _err := kms20160120.NewClient(config)
if _err != nil {
return nil, _err
}
_ramClient := &RamKmsClient{
Client: _result,
kmsVersion: constant.KMSv3,
runtime: runtimeOption,
}
return _ramClient, nil
}

func (kmsClient *RamKmsClient) GetKmsVersion() constant.KMSVersion {
return kmsClient.kmsVersion
}

func (kmsClient *RamKmsClient) setKmsVersion(kmsVersion constant.KMSVersion) {
logger.Debug("successfully set kms client version to " + kmsVersion)
kmsClient.kmsVersion = kmsVersion
}

func (kmsClient *RamKmsClient) GenerateDataKey(keyId, keySpec string) (string, string, error) {
request := &kms20160120.GenerateDataKeyRequest{
KeyId: tea.String(keyId),
KeySpec: tea.String(keySpec),
}

_body, _err := kmsClient.Client.GenerateDataKeyWithOptions(request, kmsClient.runtime)

if _err != nil {
return "", "", _err
}
return *_body.Body.Plaintext, *_body.Body.CiphertextBlob, nil
}

func (kmsClient *RamKmsClient) Decrypt(cipherContent string) (string, error) {
request := &kms20160120.DecryptRequest{
CiphertextBlob: tea.String(cipherContent),
}

_body, _err := kmsClient.Client.DecryptWithOptions(request, kmsClient.runtime)
if _err != nil {
return "", _err
}
return *_body.Body.Plaintext, nil
}

func (kmsClient *RamKmsClient) Encrypt(content, keyId string) (string, error) {
request := &kms20160120.EncryptRequest{
Plaintext: tea.String(content),
KeyId: tea.String(keyId),
}
_body, _err := kmsClient.Client.EncryptWithOptions(request, kmsClient.runtime)
if _err != nil {
return "", _err
}
return *_body.Body.CiphertextBlob, nil
}
2 changes: 1 addition & 1 deletion common/encryption/kms_plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

type kmsPlugin struct {
kmsClient *KmsClient
kmsClient KmsClient
}

func (k *kmsPlugin) Encrypt(param *HandlerParam) error {
Expand Down
Loading

0 comments on commit 7c3b1dc

Please sign in to comment.