Skip to content

Commit

Permalink
Add profile credentials provider
Browse files Browse the repository at this point in the history
  • Loading branch information
JacksonTian committed Aug 20, 2024
1 parent a7ec9d5 commit 1cd9391
Show file tree
Hide file tree
Showing 3 changed files with 449 additions and 0 deletions.
73 changes: 73 additions & 0 deletions credentials/internal/providers/fixtures/.alibabacloud/credentials
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
[default]
enable = true
type = access_key
access_key_id = foo
access_key_secret = bar

[notype]
access_key_id = foo
access_key_secret = bar

[noak]
type = access_key
access_key_secret = bar

[emptyak]
type = access_key
access_key_id =
access_key_secret = bar

[ecs]
type = ecs_ram_role
role_name = EcsRamRoleTest

[noecs]
type = ecs_ram_role

[emptyecs]
type = ecs_ram_role
role_name =

[ram]
type = ram_role_arn
access_key_id = foo
access_key_secret = bar
role_arn = role_arn
role_session_name = session_name

[noram]
type = ram_role_arn
access_key_secret = bar
role_arn = role_arn
role_session_name = session_name

[emptyram]
type = ram_role_arn
access_key_id =
access_key_secret = bar
role_arn = role_arn
role_session_name = session_name

[rsa]
type = rsa_key_pair
public_key_id = publicKeyId
private_key_file = ./pk.pem

[norsa]
type = rsa_key_pair
public_key_id = publicKeyId

[emptyrsa]
type = rsa_key_pair
public_key_id = publicKeyId
private_key_file =

[error_rsa]
type = rsa_key_pair
public_key_id = publicKeyId
private_key_file = ./pk_error.pem

[error_type]
type = error_type
public_key_id = publicKeyId
private_key_file = ./pk_error.pem
144 changes: 144 additions & 0 deletions credentials/internal/providers/profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package providers

import (
"errors"
"fmt"
"os"
"path"

"github.com/aliyun/credentials-go/credentials/internal/utils"
"gopkg.in/ini.v1"
)

type ProfileCredentialsProvider struct {
profileName string
innerProvider CredentialsProvider
}

type ProfileCredentialsProviderBuilder struct {
provider *ProfileCredentialsProvider
}

func NewProfileCredentialsProviderBuilder() (builder *ProfileCredentialsProviderBuilder) {
return &ProfileCredentialsProviderBuilder{
provider: &ProfileCredentialsProvider{},
}
}

func (b *ProfileCredentialsProviderBuilder) WithProfileName(profileName string) *ProfileCredentialsProviderBuilder {
b.provider.profileName = profileName
return b
}

func (b *ProfileCredentialsProviderBuilder) Build() (provider *ProfileCredentialsProvider) {
// 优先级:
// 1. 使用显示指定的 profileName
// 2. 使用环境变量(ALIBABA_CLOUD_PROFILE)指定的 profileName
// 3. 兜底使用 default 作为 profileName
b.provider.profileName = utils.GetDefaultString(b.provider.profileName, os.Getenv("ALIBABA_CLOUD_PROFILE"), "default")

provider = b.provider
return
}

func (provider *ProfileCredentialsProvider) getCredentialsProvider(ini *ini.File) (credentialsProvider CredentialsProvider, err error) {
section, err := ini.GetSection(provider.profileName)
if err != nil {
err = errors.New("ERROR: Can not load section" + err.Error())
return
}

value, err := section.GetKey("type")
if err != nil {
err = errors.New("ERROR: Can not find credential type" + err.Error())
return
}

switch value.String() {
case "access_key":
value1, err1 := section.GetKey("access_key_id")
value2, err2 := section.GetKey("access_key_secret")
if err1 != nil || err2 != nil {
err = errors.New("ERROR: Failed to get value")
return
}

if value1.String() == "" || value2.String() == "" {
err = errors.New("ERROR: Value can't be empty")
return
}

credentialsProvider, err = NewStaticAKCredentialsProviderBuilder().
WithAccessKeyId(value1.String()).
WithAccessKeySecret(value2.String()).
Build()
case "ecs_ram_role":
value1, err1 := section.GetKey("role_name")
if err1 != nil {
err = errors.New("ERROR: Failed to get value")
return
}
credentialsProvider, err = NewECSRAMRoleCredentialsProviderBuilder().WithRoleName(value1.String()).Build()
case "ram_role_arn":
value1, err1 := section.GetKey("access_key_id")
value2, err2 := section.GetKey("access_key_secret")
value3, err3 := section.GetKey("role_arn")
value4, err4 := section.GetKey("role_session_name")
if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
err = errors.New("ERROR: Failed to get value")
return
}
if value1.String() == "" || value2.String() == "" || value3.String() == "" || value4.String() == "" {
err = errors.New("ERROR: Value can't be empty")
return
}
previous, err5 := NewStaticAKCredentialsProviderBuilder().
WithAccessKeyId(value1.String()).
WithAccessKeySecret(value2.String()).
Build()
if err5 != nil {
err = errors.New("get previous credentials provider failed")
return
}

credentialsProvider, err = NewRAMRoleARNCredentialsProviderBuilder().
WithCredentialsProvider(previous).
WithRoleArn(value3.String()).
WithRoleSessionName(value4.String()).
WithDurationSeconds(3600).
Build()
default:
err = errors.New("ERROR: Failed to get credential")
}
return
}

func (provider *ProfileCredentialsProvider) GetCredentials() (cc *Credentials, err error) {
if provider.innerProvider != nil {
return provider.innerProvider.GetCredentials()
}

sharedCfgPath := os.Getenv("ALIBABA_CLOUD_CREDENTIALS_FILE")
if sharedCfgPath == "" {
homeDir := getHomePath()
if homeDir == "" {
err = fmt.Errorf("cannot found home dir")
return
}

sharedCfgPath = path.Join(homeDir, ".alibabacloud/credentials")
}

ini, err := ini.Load(sharedCfgPath)
if err != nil {
err = errors.New("ERROR: Can not open file" + err.Error())
return
}

provider.innerProvider, err = provider.getCredentialsProvider(ini)
if err != nil {
return
}

return provider.innerProvider.GetCredentials()
}
Loading

0 comments on commit 1cd9391

Please sign in to comment.