package provider import ( "bufio" "errors" "os" "runtime" "strings" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" ini "gopkg.in/ini.v1" ) type ProfileProvider struct { Profile string } var ProviderProfile = NewProfileProvider() // NewProfileProvider receive zero or more parameters, // when length of name is 0, the value of field Profile will be "default", // and when there are multiple inputs, the function will take the // first one and discard the other values. func NewProfileProvider(name ...string) Provider { p := new(ProfileProvider) if len(name) == 0 { p.Profile = "default" } else { p.Profile = name[0] } return p } // Resolve implements the Provider interface // when credential type is rsa_key_pair, the content of private_key file // must be able to be parsed directly into the required string // that NewRsaKeyPairCredential function needed func (p *ProfileProvider) Resolve() (auth.Credential, error) { path, ok := os.LookupEnv(ENVCredentialFile) if !ok { var err error path, err = checkDefaultPath() if err != nil { return nil, err } if path == "" { return nil, nil } } else if path == "" { return nil, errors.New("Environment variable '" + ENVCredentialFile + "' cannot be empty") } ini, err := ini.Load(path) if err != nil { return nil, errors.New("ERROR: Can not open file" + err.Error()) } section, err := ini.GetSection(p.Profile) if err != nil { return nil, errors.New("ERROR: Can not load section" + err.Error()) } value, err := section.GetKey("type") if err != nil { return nil, errors.New("ERROR: Can not find credential type" + err.Error()) } 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 { return nil, errors.New("ERROR: Failed to get value") } if value1.String() == "" || value2.String() == "" { return nil, errors.New("ERROR: Value can't be empty") } return credentials.NewAccessKeyCredential(value1.String(), value2.String()), nil case "ecs_ram_role": value1, err1 := section.GetKey("role_name") if err1 != nil { return nil, errors.New("ERROR: Failed to get value") } if value1.String() == "" { return nil, errors.New("ERROR: Value can't be empty") } return credentials.NewEcsRamRoleCredential(value1.String()), nil 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 { return nil, errors.New("ERROR: Failed to get value") } if value1.String() == "" || value2.String() == "" || value3.String() == "" || value4.String() == "" { return nil, errors.New("ERROR: Value can't be empty") } return credentials.NewRamRoleArnCredential(value1.String(), value2.String(), value3.String(), value4.String(), 3600), nil case "rsa_key_pair": value1, err1 := section.GetKey("public_key_id") value2, err2 := section.GetKey("private_key_file") if err1 != nil || err2 != nil { return nil, errors.New("ERROR: Failed to get value") } if value1.String() == "" || value2.String() == "" { return nil, errors.New("ERROR: Value can't be empty") } file, err := os.Open(value2.String()) if err != nil { return nil, errors.New("ERROR: Can not get private_key") } defer file.Close() var privateKey string scan := bufio.NewScanner(file) var data string for scan.Scan() { if strings.HasPrefix(scan.Text(), "----") { continue } data += scan.Text() + "\n" } return credentials.NewRsaKeyPairCredential(privateKey, value1.String(), 3600), nil default: return nil, errors.New("ERROR: Failed to get credential") } } // GetHomePath return home directory according to the system. // if the environmental virables does not exist, will return empty func GetHomePath() string { if runtime.GOOS == "windows" { path, ok := os.LookupEnv("USERPROFILE") if !ok { return "" } return path } path, ok := os.LookupEnv("HOME") if !ok { return "" } return path } func checkDefaultPath() (path string, err error) { path = GetHomePath() if path == "" { return "", errors.New("The default credential file path is invalid") } path = strings.Replace("~/.alibabacloud/credentials", "~", path, 1) _, err = os.Stat(path) if err != nil { return "", nil } return path, nil }