profile.go raw
1 package providers
2
3 import (
4 "errors"
5 "fmt"
6 "os"
7 "path"
8
9 "github.com/aliyun/credentials-go/credentials/internal/utils"
10 "gopkg.in/ini.v1"
11 )
12
13 type ProfileCredentialsProvider struct {
14 profileName string
15 innerProvider CredentialsProvider
16 }
17
18 type ProfileCredentialsProviderBuilder struct {
19 provider *ProfileCredentialsProvider
20 }
21
22 func NewProfileCredentialsProviderBuilder() (builder *ProfileCredentialsProviderBuilder) {
23 return &ProfileCredentialsProviderBuilder{
24 provider: &ProfileCredentialsProvider{},
25 }
26 }
27
28 func (b *ProfileCredentialsProviderBuilder) WithProfileName(profileName string) *ProfileCredentialsProviderBuilder {
29 b.provider.profileName = profileName
30 return b
31 }
32
33 func (b *ProfileCredentialsProviderBuilder) Build() (provider *ProfileCredentialsProvider, err error) {
34 // 优先级:
35 // 1. 使用显示指定的 profileName
36 // 2. 使用环境变量(ALIBABA_CLOUD_PROFILE)指定的 profileName
37 // 3. 兜底使用 default 作为 profileName
38 b.provider.profileName = utils.GetDefaultString(b.provider.profileName, os.Getenv("ALIBABA_CLOUD_PROFILE"), "default")
39
40 provider = b.provider
41 return
42 }
43
44 func (provider *ProfileCredentialsProvider) getCredentialsProvider(ini *ini.File) (credentialsProvider CredentialsProvider, err error) {
45 section, err := ini.GetSection(provider.profileName)
46 if err != nil {
47 err = errors.New("ERROR: Can not load section" + err.Error())
48 return
49 }
50
51 value, err := section.GetKey("type")
52 if err != nil {
53 err = errors.New("ERROR: Can not find credential type" + err.Error())
54 return
55 }
56
57 switch value.String() {
58 case "access_key":
59 value1, err1 := section.GetKey("access_key_id")
60 value2, err2 := section.GetKey("access_key_secret")
61 if err1 != nil || err2 != nil {
62 err = errors.New("ERROR: Failed to get value")
63 return
64 }
65
66 if value1.String() == "" || value2.String() == "" {
67 err = errors.New("ERROR: Value can't be empty")
68 return
69 }
70
71 credentialsProvider, err = NewStaticAKCredentialsProviderBuilder().
72 WithAccessKeyId(value1.String()).
73 WithAccessKeySecret(value2.String()).
74 Build()
75 case "ecs_ram_role":
76 value1, err1 := section.GetKey("role_name")
77 if err1 != nil {
78 err = errors.New("ERROR: Failed to get value")
79 return
80 }
81 credentialsProvider, err = NewECSRAMRoleCredentialsProviderBuilder().WithRoleName(value1.String()).Build()
82 case "ram_role_arn":
83 value1, err1 := section.GetKey("access_key_id")
84 value2, err2 := section.GetKey("access_key_secret")
85 value3, err3 := section.GetKey("role_arn")
86 value4, err4 := section.GetKey("role_session_name")
87 if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
88 err = errors.New("ERROR: Failed to get value")
89 return
90 }
91 if value1.String() == "" || value2.String() == "" || value3.String() == "" || value4.String() == "" {
92 err = errors.New("ERROR: Value can't be empty")
93 return
94 }
95 previous, err5 := NewStaticAKCredentialsProviderBuilder().
96 WithAccessKeyId(value1.String()).
97 WithAccessKeySecret(value2.String()).
98 Build()
99 if err5 != nil {
100 err = errors.New("get previous credentials provider failed")
101 return
102 }
103 rawPolicy, _ := section.GetKey("policy")
104 policy := ""
105 if rawPolicy != nil {
106 policy = rawPolicy.String()
107 }
108
109 credentialsProvider, err = NewRAMRoleARNCredentialsProviderBuilder().
110 WithCredentialsProvider(previous).
111 WithRoleArn(value3.String()).
112 WithRoleSessionName(value4.String()).
113 WithPolicy(policy).
114 WithDurationSeconds(3600).
115 Build()
116 default:
117 err = errors.New("ERROR: Failed to get credential")
118 }
119 return
120 }
121
122 func (provider *ProfileCredentialsProvider) GetCredentials() (cc *Credentials, err error) {
123 if provider.innerProvider == nil {
124 sharedCfgPath := os.Getenv("ALIBABA_CLOUD_CREDENTIALS_FILE")
125 if sharedCfgPath == "" {
126 homeDir := getHomePath()
127 if homeDir == "" {
128 err = fmt.Errorf("cannot found home dir")
129 return
130 }
131
132 sharedCfgPath = path.Join(homeDir, ".alibabacloud/credentials")
133 }
134
135 ini, err1 := ini.Load(sharedCfgPath)
136 if err1 != nil {
137 err = errors.New("ERROR: Can not open file" + err1.Error())
138 return
139 }
140
141 provider.innerProvider, err = provider.getCredentialsProvider(ini)
142 if err != nil {
143 return
144 }
145 }
146
147 innerCC, err := provider.innerProvider.GetCredentials()
148 if err != nil {
149 return
150 }
151
152 providerName := innerCC.ProviderName
153 if providerName == "" {
154 providerName = provider.innerProvider.GetProviderName()
155 }
156
157 cc = &Credentials{
158 AccessKeyId: innerCC.AccessKeyId,
159 AccessKeySecret: innerCC.AccessKeySecret,
160 SecurityToken: innerCC.SecurityToken,
161 ProviderName: fmt.Sprintf("%s/%s", provider.GetProviderName(), providerName),
162 }
163
164 return
165 }
166
167 func (provider *ProfileCredentialsProvider) GetProviderName() string {
168 return "profile"
169 }
170