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

feat: add imds and external uri in default chain && resolve credentia… #126

Merged
merged 1 commit into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 45 additions & 27 deletions credentials/credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,50 @@ type Credential interface {

// Config is important when call NewCredential
type Config struct {
Type *string `json:"type"`
AccessKeyId *string `json:"access_key_id"`
AccessKeySecret *string `json:"access_key_secret"`
OIDCProviderArn *string `json:"oidc_provider_arn"`
OIDCTokenFilePath *string `json:"oidc_token"`
RoleArn *string `json:"role_arn"`
RoleSessionName *string `json:"role_session_name"`
PublicKeyId *string `json:"public_key_id"`
RoleName *string `json:"role_name"`
EnableIMDSv2 *bool `json:"enable_imds_v2"`
DisableIMDSv1 *bool `json:"disable_imds_v1"`
MetadataTokenDuration *int `json:"metadata_token_duration"`
SessionExpiration *int `json:"session_expiration"`
PrivateKeyFile *string `json:"private_key_file"`
BearerToken *string `json:"bearer_token"`
SecurityToken *string `json:"security_token"`
RoleSessionExpiration *int `json:"role_session_expiration"`
Policy *string `json:"policy"`
Host *string `json:"host"`
Timeout *int `json:"timeout"`
ConnectTimeout *int `json:"connect_timeout"`
Proxy *string `json:"proxy"`
InAdvanceScale *float64 `json:"inAdvanceScale"`
Url *string `json:"url"`
STSEndpoint *string `json:"sts_endpoint"`
ExternalId *string `json:"external_id"`
// Credential type, including access_key, sts, bearer, ecs_ram_role, ram_role_arn, rsa_key_pair, oidc_role_arn, credentials_uri
Type *string `json:"type"`
AccessKeyId *string `json:"access_key_id"`
AccessKeySecret *string `json:"access_key_secret"`
SecurityToken *string `json:"security_token"`
BearerToken *string `json:"bearer_token"`

// Used when the type is ram_role_arn or oidc_role_arn
OIDCProviderArn *string `json:"oidc_provider_arn"`
OIDCTokenFilePath *string `json:"oidc_token"`
RoleArn *string `json:"role_arn"`
RoleSessionName *string `json:"role_session_name"`
RoleSessionExpiration *int `json:"role_session_expiration"`
Policy *string `json:"policy"`
ExternalId *string `json:"external_id"`
STSEndpoint *string `json:"sts_endpoint"`

// Used when the type is ecs_ram_role
RoleName *string `json:"role_name"`
// Deprecated
EnableIMDSv2 *bool `json:"enable_imds_v2"`
DisableIMDSv1 *bool `json:"disable_imds_v1"`
// Deprecated
MetadataTokenDuration *int `json:"metadata_token_duration"`

// Used when the type is credentials_uri
Url *string `json:"url"`

// Deprecated
// Used when the type is rsa_key_pair
SessionExpiration *int `json:"session_expiration"`
PublicKeyId *string `json:"public_key_id"`
PrivateKeyFile *string `json:"private_key_file"`
Host *string `json:"host"`

// Read timeout, in milliseconds.
// The default value for ecs_ram_role is 1000ms, the default value for ram_role_arn is 5000ms, and the default value for oidc_role_arn is 5000ms.
Timeout *int `json:"timeout"`
// Connection timeout, in milliseconds.
// The default value for ecs_ram_role is 1000ms, the default value for ram_role_arn is 10000ms, and the default value for oidc_role_arn is 10000ms.
ConnectTimeout *int `json:"connect_timeout"`

Proxy *string `json:"proxy"`
InAdvanceScale *float64 `json:"inAdvanceScale"`
}

func (s Config) String() string {
Expand Down Expand Up @@ -343,7 +361,7 @@ func NewCredential(config *Config) (credential Credential, err error) {
}
credential = newBearerTokenCredential(tea.StringValue(config.BearerToken))
default:
err = errors.New("invalid type option, support: access_key, sts, ecs_ram_role, ram_role_arn, rsa_key_pair")
err = errors.New("invalid type option, support: access_key, sts, bearer, ecs_ram_role, ram_role_arn, rsa_key_pair, oidc_role_arn, credentials_uri")
return
}
return credential, nil
Expand Down
6 changes: 3 additions & 3 deletions credentials/credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ this is privatekey`

func TestConfig(t *testing.T) {
config := new(Config)
assert.Equal(t, "{\n \"type\": null,\n \"access_key_id\": null,\n \"access_key_secret\": null,\n \"oidc_provider_arn\": null,\n \"oidc_token\": null,\n \"role_arn\": null,\n \"role_session_name\": null,\n \"public_key_id\": null,\n \"role_name\": null,\n \"enable_imds_v2\": null,\n \"disable_imds_v1\": null,\n \"metadata_token_duration\": null,\n \"session_expiration\": null,\n \"private_key_file\": null,\n \"bearer_token\": null,\n \"security_token\": null,\n \"role_session_expiration\": null,\n \"policy\": null,\n \"host\": null,\n \"timeout\": null,\n \"connect_timeout\": null,\n \"proxy\": null,\n \"inAdvanceScale\": null,\n \"url\": null,\n \"sts_endpoint\": null,\n \"external_id\": null\n}", config.String())
assert.Equal(t, "{\n \"type\": null,\n \"access_key_id\": null,\n \"access_key_secret\": null,\n \"oidc_provider_arn\": null,\n \"oidc_token\": null,\n \"role_arn\": null,\n \"role_session_name\": null,\n \"public_key_id\": null,\n \"role_name\": null,\n \"enable_imds_v2\": null,\n \"disable_imds_v1\": null,\n \"metadata_token_duration\": null,\n \"session_expiration\": null,\n \"private_key_file\": null,\n \"bearer_token\": null,\n \"security_token\": null,\n \"role_session_expiration\": null,\n \"policy\": null,\n \"host\": null,\n \"timeout\": null,\n \"connect_timeout\": null,\n \"proxy\": null,\n \"inAdvanceScale\": null,\n \"url\": null,\n \"sts_endpoint\": null,\n \"external_id\": null\n}", config.GoString())
assert.Equal(t, "{\n \"type\": null,\n \"access_key_id\": null,\n \"access_key_secret\": null,\n \"security_token\": null,\n \"bearer_token\": null,\n \"oidc_provider_arn\": null,\n \"oidc_token\": null,\n \"role_arn\": null,\n \"role_session_name\": null,\n \"role_session_expiration\": null,\n \"policy\": null,\n \"external_id\": null,\n \"sts_endpoint\": null,\n \"role_name\": null,\n \"enable_imds_v2\": null,\n \"disable_imds_v1\": null,\n \"metadata_token_duration\": null,\n \"url\": null,\n \"session_expiration\": null,\n \"public_key_id\": null,\n \"private_key_file\": null,\n \"host\": null,\n \"timeout\": null,\n \"connect_timeout\": null,\n \"proxy\": null,\n \"inAdvanceScale\": null\n}", config.String())
assert.Equal(t, "{\n \"type\": null,\n \"access_key_id\": null,\n \"access_key_secret\": null,\n \"security_token\": null,\n \"bearer_token\": null,\n \"oidc_provider_arn\": null,\n \"oidc_token\": null,\n \"role_arn\": null,\n \"role_session_name\": null,\n \"role_session_expiration\": null,\n \"policy\": null,\n \"external_id\": null,\n \"sts_endpoint\": null,\n \"role_name\": null,\n \"enable_imds_v2\": null,\n \"disable_imds_v1\": null,\n \"metadata_token_duration\": null,\n \"url\": null,\n \"session_expiration\": null,\n \"public_key_id\": null,\n \"private_key_file\": null,\n \"host\": null,\n \"timeout\": null,\n \"connect_timeout\": null,\n \"proxy\": null,\n \"inAdvanceScale\": null\n}", config.GoString())

config.SetSTSEndpoint("sts.cn-hangzhou.aliyuncs.com")
assert.Equal(t, "sts.cn-hangzhou.aliyuncs.com", *config.STSEndpoint)
Expand Down Expand Up @@ -309,7 +309,7 @@ func TestNewCredentialWithInvalidType(t *testing.T) {
config.SetType("sdk")
cred, err := NewCredential(config)
assert.NotNil(t, err)
assert.Equal(t, "invalid type option, support: access_key, sts, ecs_ram_role, ram_role_arn, rsa_key_pair", err.Error())
assert.Equal(t, "invalid type option, support: access_key, sts, bearer, ecs_ram_role, ram_role_arn, rsa_key_pair, oidc_role_arn, credentials_uri", err.Error())
assert.Nil(t, cred)
}

Expand Down
7 changes: 7 additions & 0 deletions credentials/internal/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

type Request struct {
Method string // http request method
URL string // http url
Protocol string // http or https
Host string // http host
ReadTimeout time.Duration
Expand All @@ -31,6 +32,9 @@ type Request struct {

func (req *Request) BuildRequestURL() string {
httpUrl := fmt.Sprintf("%s://%s%s", req.Protocol, req.Host, req.Path)
if req.URL != "" {
httpUrl = req.URL
}

querystring := utils.GetURLFormedMap(req.Queries)
if querystring != "" {
Expand Down Expand Up @@ -60,6 +64,9 @@ func Do(req *Request) (res *Response, err error) {
querystring := utils.GetURLFormedMap(req.Queries)
// do request
httpUrl := fmt.Sprintf("%s://%s%s?%s", req.Protocol, req.Host, req.Path, querystring)
if req.URL != "" {
httpUrl = req.URL
}

var body io.Reader
if req.Method == "GET" {
Expand Down
18 changes: 18 additions & 0 deletions credentials/internal/http/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ func TestRequest(t *testing.T) {
Path: "/",
}
assert.Equal(t, "GET http://www.aliyun.com/", req.BuildRequestURL())

req = &Request{
Method: "GET",
URL: "http://www.aliyun.com",
Path: "/",
}
assert.Equal(t, "GET http://www.aliyun.com", req.BuildRequestURL())

// With query
req = &Request{
Method: "GET",
Expand All @@ -44,6 +52,16 @@ func TestDoGet(t *testing.T) {
assert.NotNil(t, res)
assert.Equal(t, 200, res.StatusCode)
assert.Equal(t, "text/html; charset=utf-8", res.Headers["Content-Type"])

req = &Request{
Method: "GET",
URL: "http://www.aliyun.com",
}
res, err = Do(req)
assert.Nil(t, err)
assert.NotNil(t, res)
assert.Equal(t, 200, res.StatusCode)
assert.Equal(t, "text/html; charset=utf-8", res.Headers["Content-Type"])
}

func TestDoPost(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion credentials/providers/cli_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io/ioutil"
"os"
"path"
"strings"

"github.com/aliyun/credentials-go/credentials/internal/utils"
)
Expand Down Expand Up @@ -34,7 +35,7 @@ func (b *CLIProfileCredentialsProviderBuilder) Build() (provider *CLIProfileCred
b.provider.profileName = os.Getenv("ALIBABA_CLOUD_PROFILE")
}

if os.Getenv("ALIBABA_CLOUD_CLI_PROFILE_DISABLED") == "true" {
if strings.ToLower(os.Getenv("ALIBABA_CLOUD_CLI_PROFILE_DISABLED")) == "true" {
err = errors.New("the CLI profile is disabled")
return
}
Expand Down
9 changes: 8 additions & 1 deletion credentials/providers/cli_profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

func TestCLIProfileCredentialsProvider(t *testing.T) {
rollback := utils.Memory("ALIBABA_CLOUD_PROFILE")
rollback := utils.Memory("ALIBABA_CLOUD_PROFILE", "ALIBABA_CLOUD_CLI_PROFILE_DISABLED")
defer rollback()

b, err := NewCLIProfileCredentialsProviderBuilder().
Expand All @@ -31,6 +31,13 @@ func TestCLIProfileCredentialsProvider(t *testing.T) {
Build()
assert.Nil(t, err)
assert.Equal(t, "profilename", b.profileName)

os.Setenv("ALIBABA_CLOUD_CLI_PROFILE_DISABLED", "True")
_, err = NewCLIProfileCredentialsProviderBuilder().
WithProfileName("profilename").
Build()
assert.Equal(t, "the CLI profile is disabled", err.Error())

}

func Test_configuration(t *testing.T) {
Expand Down
14 changes: 9 additions & 5 deletions credentials/providers/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,19 @@ func NewDefaultCredentialsProvider() (provider *DefaultCredentialsProvider) {
}

// Add IMDS
if os.Getenv("ALIBABA_CLOUD_ECS_METADATA") != "" {
ecsRamRoleProvider, err := NewECSRAMRoleCredentialsProviderBuilder().WithRoleName(os.Getenv("ALIBABA_CLOUD_ECS_METADATA")).Build()
ecsRamRoleProvider, err := NewECSRAMRoleCredentialsProviderBuilder().Build()
if err == nil {
providers = append(providers, ecsRamRoleProvider)
}

// credentials uri
if os.Getenv("ALIBABA_CLOUD_CREDENTIALS_URI") != "" {
credentialsUriProvider, err := NewURLCredentialsProviderBuilderBuilder().Build()
if err == nil {
providers = append(providers, ecsRamRoleProvider)
providers = append(providers, credentialsUriProvider)
}
}

// TODO: ALIBABA_CLOUD_CREDENTIALS_URI check

return &DefaultCredentialsProvider{
providerChain: providers,
}
Expand Down
42 changes: 37 additions & 5 deletions credentials/providers/default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
func TestDefaultCredentialsProvider(t *testing.T) {
provider := NewDefaultCredentialsProvider()
assert.NotNil(t, provider)
assert.Len(t, provider.providerChain, 3)
assert.Len(t, provider.providerChain, 4)
_, ok := provider.providerChain[0].(*EnvironmentVariableCredentialsProvider)
assert.True(t, ok)

Expand All @@ -21,11 +21,15 @@ func TestDefaultCredentialsProvider(t *testing.T) {
_, ok = provider.providerChain[2].(*ProfileCredentialsProvider)
assert.True(t, ok)

_, ok = provider.providerChain[3].(*ECSRAMRoleCredentialsProvider)
assert.True(t, ok)

// Add oidc provider
rollback := utils.Memory("ALIBABA_CLOUD_OIDC_TOKEN_FILE",
"ALIBABA_CLOUD_OIDC_PROVIDER_ARN",
"ALIBABA_CLOUD_ROLE_ARN",
"ALIBABA_CLOUD_ECS_METADATA")
"ALIBABA_CLOUD_ECS_METADATA",
"ALIBABA_CLOUD_CREDENTIALS_URI")

defer rollback()
os.Setenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE", "/path/to/oidc.token")
Expand All @@ -34,7 +38,7 @@ func TestDefaultCredentialsProvider(t *testing.T) {

provider = NewDefaultCredentialsProvider()
assert.NotNil(t, provider)
assert.Len(t, provider.providerChain, 4)
assert.Len(t, provider.providerChain, 5)
_, ok = provider.providerChain[0].(*EnvironmentVariableCredentialsProvider)
assert.True(t, ok)

Expand All @@ -47,7 +51,10 @@ func TestDefaultCredentialsProvider(t *testing.T) {
_, ok = provider.providerChain[3].(*ProfileCredentialsProvider)
assert.True(t, ok)

// Add ecs ram role
_, ok = provider.providerChain[4].(*ECSRAMRoleCredentialsProvider)
assert.True(t, ok)

// Add ecs ram role name
os.Setenv("ALIBABA_CLOUD_ECS_METADATA", "rolename")
provider = NewDefaultCredentialsProvider()
assert.NotNil(t, provider)
Expand All @@ -66,12 +73,36 @@ func TestDefaultCredentialsProvider(t *testing.T) {

_, ok = provider.providerChain[4].(*ECSRAMRoleCredentialsProvider)
assert.True(t, ok)

// Add ecs ram role
os.Setenv("ALIBABA_CLOUD_CREDENTIALS_URI", "http://")
provider = NewDefaultCredentialsProvider()
assert.NotNil(t, provider)
assert.Len(t, provider.providerChain, 6)
_, ok = provider.providerChain[0].(*EnvironmentVariableCredentialsProvider)
assert.True(t, ok)

_, ok = provider.providerChain[1].(*OIDCCredentialsProvider)
assert.True(t, ok)

_, ok = provider.providerChain[2].(*CLIProfileCredentialsProvider)
assert.True(t, ok)

_, ok = provider.providerChain[3].(*ProfileCredentialsProvider)
assert.True(t, ok)

_, ok = provider.providerChain[4].(*ECSRAMRoleCredentialsProvider)
assert.True(t, ok)

_, ok = provider.providerChain[5].(*URLCredentialsProvider)
assert.True(t, ok)
}

func TestDefaultCredentialsProvider_GetCredentials(t *testing.T) {
rollback := utils.Memory("ALIBABA_CLOUD_ACCESS_KEY_ID",
"ALIBABA_CLOUD_ACCESS_KEY_SECRET",
"ALIBABA_CLOUD_SECURITY_TOKEN")
"ALIBABA_CLOUD_SECURITY_TOKEN",
"ALIBABA_CLOUD_ECS_METADATA_DISABLED")

defer func() {
getHomePath = utils.GetHomePath
Expand All @@ -83,6 +114,7 @@ func TestDefaultCredentialsProvider_GetCredentials(t *testing.T) {
return ""
}

os.Setenv("ALIBABA_CLOUD_ECS_METADATA_DISABLED", "true")
provider := NewDefaultCredentialsProvider()
assert.Len(t, provider.providerChain, 3)
_, err := provider.GetCredentials()
Expand Down
Loading