Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alibaba SDK SSM #317

Merged
merged 16 commits into from
Aug 12, 2024
4 changes: 2 additions & 2 deletions command/secrets/generate/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ const (

var (
errUnsupportedType = fmt.Errorf(
"unsupported service manager type; only %s, %s, %s and %s are supported for now",
secrets.Local, secrets.HashicorpVault, secrets.AWSSSM, secrets.GCPSSM)
"unsupported service manager type; only %s, %s, %s, %s and %s are supported for now",
secrets.Local, secrets.HashicorpVault, secrets.AWSSSM, secrets.GCPSSM, secrets.AlibabaSSM)
)

type generateParams struct {
Expand Down
3 changes: 2 additions & 1 deletion command/secrets/generate/secrets_generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ func setFlags(cmd *cobra.Command) {
typeFlag,
string(secrets.HashicorpVault),
fmt.Sprintf(
"the type of the secrets manager. Available types: %s, %s and %s",
"the type of the secrets manager. Available types: %s, %s, %s and %s",
secrets.HashicorpVault,
secrets.AWSSSM,
secrets.GCPSSM,
secrets.AlibabaSSM,
),
)

Expand Down
23 changes: 20 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ require (
github.com/Ethernal-Tech/blockchain-event-tracker v0.0.0-20240628125004-67308570b6e2
github.com/Ethernal-Tech/ethgo v0.0.0-20240801172627-47215d9e504c
github.com/Ethernal-Tech/merkle-tree v0.0.0-20231213143318-4db9da419e04
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.8
github.com/alibabacloud-go/oos-20190601/v4 v4.1.2
github.com/alibabacloud-go/tea v1.2.2
github.com/alibabacloud-go/tea-utils/v2 v2.0.6
github.com/aliyun/credentials-go v1.3.6
github.com/armon/go-metrics v0.4.1
github.com/aws/aws-sdk-go v1.55.5
github.com/btcsuite/btcd/btcec/v2 v2.3.4
Expand Down Expand Up @@ -57,6 +62,20 @@ require (
pgregory.net/rapid v1.1.0
)

require (
github.com/DataDog/go-libddwaf/v3 v3.2.1 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect
github.com/alibabacloud-go/debug v1.0.0 // indirect
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
github.com/alibabacloud-go/tea-utils v1.3.1 // indirect
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20240503222823-736c933a666d // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)

require (
cloud.google.com/go/auth v0.7.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect
Expand All @@ -67,7 +86,6 @@ require (
github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0 // indirect
github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.1 // indirect
github.com/DataDog/datadog-go/v5 v5.3.0 // indirect
github.com/DataDog/go-libddwaf/v3 v3.2.1 // indirect
github.com/DataDog/go-tuf v1.0.2-0.5.2 // indirect
github.com/DataDog/gostackparse v0.7.0 // indirect
github.com/DataDog/sketches-go v1.4.5 // indirect
Expand Down Expand Up @@ -124,7 +142,6 @@ require (
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20240503222823-736c933a666d // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/boxo v0.8.1 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
Expand Down Expand Up @@ -176,7 +193,7 @@ require (
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opencontainers/runc v1.1.13 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/ory/dockertest v3.3.5+incompatible // indirect
github.com/outcaste-io/ristretto v0.2.3 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
Expand Down
68 changes: 67 additions & 1 deletion go.sum

Large diffs are not rendered by default.

256 changes: 256 additions & 0 deletions secrets/alibaba/alibaba_ssm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
package alibabassm

import (
"encoding/json"
"errors"
"fmt"
"strings"

"github.com/0xPolygon/polygon-edge/secrets"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
oos20190601 "github.com/alibabacloud-go/oos-20190601/v4/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
aliyun "github.com/aliyun/credentials-go/credentials"
"github.com/hashicorp/go-hclog"
)

type AlibabaSsmManager struct {
// Local logger object
logger hclog.Logger

// The Alibaba region
region string

// Custom Alibaba endpoint, e.g. localstack
endpoint string

// The Alibaba SDK client
client *oos20190601.Client

// The base path to store the secrets in OOS Parameter Store
basePath string

// The role name assigned to OOS service
role string
}

func SecretsManagerFactory(
config *secrets.SecretsManagerConfig,
params *secrets.SecretsManagerParams) (secrets.SecretsManager, error) { //nolint

// Check if the node name is present
if config.Name == "" {
return nil, errors.New("no node name specified for Alibaba secrets manager")
}

// Check if the extra map is present
if config.Extra == nil ||
config.Extra["region"] == nil ||
config.Extra["ssm-parameter-path"] == nil ||
config.Extra["role"] == nil {
return nil, errors.New("required extra map containing 'region' and 'ssm-parameter-path' " +
"and 'role' not found for alibaba-ssm")
}

// / Set up the base object
alibabaSsmManager := &AlibabaSsmManager{
logger: params.Logger.Named(string(secrets.AlibabaSSM)),
region: fmt.Sprintf("%v", config.Extra["region"]),
role: fmt.Sprintf("%v", config.Extra["role"]),
endpoint: config.ServerURL,
}

// Set the base path to store the secrets in OOS parameter store
alibabaSsmManager.basePath = fmt.Sprintf("%s/%s", config.Extra["ssm-parameter-path"], config.Name)

// Run the initial setup
if err := alibabaSsmManager.Setup(); err != nil {
return nil, err
}

return alibabaSsmManager, nil
}

// Setup sets up the Alibaba secrets manager
func (a *AlibabaSsmManager) Setup() error {
creds, err := getCredentials(a.role)
if err != nil {
return err
}

config := &openapi.Config{
// Required
AccessKeyId: creds.AccessKeyId,
// Required
AccessKeySecret: creds.AccessKeySecret,
// Required
SecurityToken: creds.SecurityToken,
// config.Endpoint = tea.String("oos.eu-central-1.aliyuncs.com")
Endpoint: tea.String(a.endpoint),
// eu-central-1
RegionId: tea.String(a.region),
}

client, err := oos20190601.NewClient(config)
if err != nil {
return err
}

a.client = client

return nil
}

// constructSecretPath is a helper method for constructing a path to the secret
func (a *AlibabaSsmManager) constructSecretPath(name string) string {
return fmt.Sprintf("%s/%s", a.basePath, name)
}

// GetSecret fetches a secret from Alibaba OOS parameter store
func (a *AlibabaSsmManager) GetSecret(name string) ([]byte, error) {
getSecretParameterRequest := &oos20190601.GetSecretParameterRequest{
RegionId: tea.String(a.region), // eu-central-1
Name: tea.String(a.constructSecretPath(name)),
WithDecryption: tea.Bool(true),
}
runtime := &util.RuntimeOptions{}
retVal, tryErr := func() (_b []byte, _e error) {
defer func() {
if r := tea.Recover(recover()); r != nil {
_b = nil
_e = r
}
}()

response, err := a.client.GetSecretParameterWithOptions(getSecretParameterRequest, runtime)
if err != nil {
return nil, err
}

return []byte(tea.StringValue(response.Body.Parameter.Value)), nil
}()

if tryErr != nil {
a.logError(tryErr)
}

return retVal, tryErr
}

// SetSecret saves a secret to Alibaba OOS oaarmeter store
func (a *AlibabaSsmManager) SetSecret(name string, value []byte) error {
createSecretParameterRequest := &oos20190601.CreateSecretParameterRequest{
RegionId: tea.String(a.region), // eu-central-1
Name: tea.String(a.constructSecretPath(name)),
Value: tea.String(string(value)),
}
runtime := &util.RuntimeOptions{}
tryErr := func() (_e error) {
defer func() {
if r := tea.Recover(recover()); r != nil {
_e = r
}
}()

_, err := a.client.CreateSecretParameterWithOptions(createSecretParameterRequest, runtime)
if err != nil {
return err
}

return nil
}()

if tryErr != nil {
a.logError(tryErr)
}

return tryErr
}

// HasSecret checks if the secret is present on Alibabab OOS parameter store
func (a *AlibabaSsmManager) HasSecret(name string) bool {
_, err := a.GetSecret(name)

return err == nil
}

// RemoveSecret removes a secret from Alibaba OOS parameter store
func (a *AlibabaSsmManager) RemoveSecret(name string) error {
deleteSecretParameterRequest := &oos20190601.DeleteSecretParameterRequest{
RegionId: tea.String(a.region),
Name: tea.String(a.constructSecretPath(name)),
}
runtime := &util.RuntimeOptions{}
tryErr := func() (_e error) {
defer func() {
if r := tea.Recover(recover()); r != nil {
_e = r
}
}()

_, err := a.client.DeleteSecretParameterWithOptions(deleteSecretParameterRequest, runtime)
if err != nil {
return err
}

return nil
}()

if tryErr != nil {
a.logError(tryErr)
}

return tryErr
}

func (a *AlibabaSsmManager) logError(err error) {
var e *tea.SDKError
if ok := errors.As(err, &e); !ok {
e = &tea.SDKError{Message: tea.String(err.Error())}
}

_, err = util.AssertAsString(e.Message)
if err != nil {
a.logger.Error("unable to log error message")

return
}

a.logger.Error(tea.StringValue(e.Message))

var data interface{}

d := json.NewDecoder(strings.NewReader(tea.StringValue(e.Data)))

err = d.Decode(&data)
if err != nil {
a.logger.Error("unable to decode recommendation", err)

return
}

if m, ok := data.(map[string]interface{}); ok {
recommend := m["Recommend"]
a.logger.Info("recommend", recommend)
}
}

func getCredentials(role string) (*aliyun.CredentialModel, error) {
config := new(aliyun.Config).
// Which type of credential you want
SetType("ecs_ram_role").
// `roleName` is optional. It will be retrieved automatically if not set.
// It is highly recommended to set it up to reduce requests
SetRoleName(role).
// `EnableIMDSv2` is optional and is recommended to be turned on.
// It can be replaced by setting environment variable: ALIBABA_CLOUD_ECS_IMDSV2_ENABLE
SetEnableIMDSv2(true)

creds, err := aliyun.NewCredential(config)
if err != nil {
return nil, err
}

return creds.GetCredential()
}
20 changes: 20 additions & 0 deletions secrets/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/0xPolygon/polygon-edge/helper/hex"
"github.com/0xPolygon/polygon-edge/network"
"github.com/0xPolygon/polygon-edge/secrets"
alibabassm "github.com/0xPolygon/polygon-edge/secrets/alibaba"
"github.com/0xPolygon/polygon-edge/secrets/awsssm"
"github.com/0xPolygon/polygon-edge/secrets/gcpssm"
"github.com/0xPolygon/polygon-edge/secrets/hashicorpvault"
Expand Down Expand Up @@ -77,6 +78,18 @@ func setupGCPSSM(
)
}

// setupAlibabaSSM is a helper method for boilerplate Alibaba Cloud Computing secrets manager setup
func setupAlibabaSSM(
secretsConfig *secrets.SecretsManagerConfig,
) (secrets.SecretsManager, error) {
return alibabassm.SecretsManagerFactory(
secretsConfig,
&secrets.SecretsManagerParams{
Logger: hclog.NewNullLogger(),
},
)
}

// InitECDSAValidatorKey creates new ECDSA key and set as a validator key
func InitECDSAValidatorKey(secretsManager secrets.SecretsManager) (types.Address, error) {
if secretsManager.HasSecret(secrets.ValidatorKey) {
Expand Down Expand Up @@ -282,6 +295,13 @@ func InitCloudSecretsManager(secretsConfig *secrets.SecretsManagerConfig) (secre
}

secretsManager = GCPSSM
case secrets.AlibabaSSM:
alibabaSSM, err := setupAlibabaSSM(secretsConfig)
if err != nil {
return secretsManager, err
}

secretsManager = alibabaSSM
default:
return secretsManager, errors.New("unsupported secrets manager")
}
Expand Down
5 changes: 4 additions & 1 deletion secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ const (

// GCPSSM pertains to the Google Cloud Computing secret store manager
GCPSSM SecretsManagerType = "gcp-ssm"

// AlibabaSSM pertains to the Alibaba OOS parameter store
AlibabaSSM SecretsManagerType = "alibaba-ssm"
)

// SecretsManager defines the base public interface that all
Expand Down Expand Up @@ -119,5 +122,5 @@ type SecretsManagerFactory func(
// SupportedServiceManager checks if the passed in service manager type is supported
func SupportedServiceManager(service SecretsManagerType) bool {
return service == HashicorpVault || service == AWSSSM ||
service == Local || service == GCPSSM
service == Local || service == GCPSSM || service == AlibabaSSM
}
Loading
Loading