Skip to content

Commit

Permalink
Merge pull request #317 from Ethernal-Tech/alibaba-sdk
Browse files Browse the repository at this point in the history
Alibaba SDK SSM
  • Loading branch information
oliverbundalo authored Aug 12, 2024
2 parents 6546989 + 8f77471 commit c9e9d37
Show file tree
Hide file tree
Showing 9 changed files with 378 additions and 8 deletions.
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

0 comments on commit c9e9d37

Please sign in to comment.