github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/builder/amazon/common/cli_config.go (about) 1 package common 2 3 import ( 4 "fmt" 5 "os" 6 "path" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/aws/credentials" 10 "github.com/aws/aws-sdk-go/aws/session" 11 "github.com/aws/aws-sdk-go/service/sts" 12 "github.com/go-ini/ini" 13 "github.com/mitchellh/go-homedir" 14 ) 15 16 type CLIConfig struct { 17 ProfileName string 18 SourceProfile string 19 20 AssumeRoleInput *sts.AssumeRoleInput 21 SourceCredentials *credentials.Credentials 22 23 profileCfg *ini.Section 24 profileCred *ini.Section 25 } 26 27 // Return a new CLIConfig with stored profile settings 28 func NewFromProfile(name string) (*CLIConfig, error) { 29 c := &CLIConfig{} 30 c.AssumeRoleInput = new(sts.AssumeRoleInput) 31 err := c.Prepare(name) 32 if err != nil { 33 return nil, err 34 } 35 sessName, err := c.getSessionName(c.profileCfg.Key("role_session_name").Value()) 36 if err != nil { 37 return nil, err 38 } 39 c.AssumeRoleInput.RoleSessionName = aws.String(sessName) 40 arn := c.profileCfg.Key("role_arn").Value() 41 if arn != "" { 42 c.AssumeRoleInput.RoleArn = aws.String(arn) 43 } 44 id := c.profileCfg.Key("external_id").Value() 45 if id != "" { 46 c.AssumeRoleInput.ExternalId = aws.String(id) 47 } 48 c.SourceCredentials = credentials.NewStaticCredentials( 49 c.profileCred.Key("aws_access_key_id").Value(), 50 c.profileCred.Key("aws_secret_access_key").Value(), 51 c.profileCred.Key("aws_session_token").Value(), 52 ) 53 return c, nil 54 } 55 56 // Return AWS Credentials using current profile. Must supply source config. 57 func (c *CLIConfig) CredentialsFromProfile(conf *aws.Config) (*credentials.Credentials, error) { 58 // If the profile name is equal to the source profile, there is no role to assume so return 59 // the source credentials as they were captured. 60 if c.ProfileName == c.SourceProfile { 61 return c.SourceCredentials, nil 62 } 63 srcCfg := aws.NewConfig().Copy(conf).WithCredentials(c.SourceCredentials) 64 session, err := session.NewSession(srcCfg) 65 if err != nil { 66 return nil, err 67 } 68 svc := sts.New(session) 69 res, err := svc.AssumeRole(c.AssumeRoleInput) 70 if err != nil { 71 return nil, err 72 } 73 return credentials.NewStaticCredentials( 74 *res.Credentials.AccessKeyId, 75 *res.Credentials.SecretAccessKey, 76 *res.Credentials.SessionToken, 77 ), nil 78 } 79 80 // Sets params in the struct based on the file section 81 func (c *CLIConfig) Prepare(name string) error { 82 var err error 83 c.ProfileName = name 84 c.profileCfg, err = configFromName(c.ProfileName) 85 if err != nil { 86 return err 87 } 88 c.SourceProfile = c.profileCfg.Key("source_profile").Value() 89 if c.SourceProfile == "" { 90 c.SourceProfile = c.ProfileName 91 } 92 c.profileCred, err = credsFromName(c.SourceProfile) 93 if err != nil { 94 return err 95 } 96 return nil 97 } 98 99 func (c *CLIConfig) getSessionName(rawName string) (string, error) { 100 if rawName == "" { 101 name := "packer-" 102 host, err := os.Hostname() 103 if err != nil { 104 return name, err 105 } 106 return fmt.Sprintf("%s%s", name, host), nil 107 } else { 108 return rawName, nil 109 } 110 } 111 112 func configFromName(name string) (*ini.Section, error) { 113 filePath := os.Getenv("AWS_CONFIG_FILE") 114 if filePath == "" { 115 home, err := homedir.Dir() 116 if err != nil { 117 return nil, err 118 } 119 filePath = path.Join(home, ".aws", "config") 120 } 121 file, err := readFile(filePath) 122 if err != nil { 123 return nil, err 124 } 125 profileName := fmt.Sprintf("profile %s", name) 126 cfg, err := file.GetSection(profileName) 127 if err != nil { 128 return nil, err 129 } 130 return cfg, nil 131 } 132 133 func credsFromName(name string) (*ini.Section, error) { 134 filePath := os.Getenv("AWS_SHARED_CREDENTIALS_FILE") 135 if filePath == "" { 136 home, err := homedir.Dir() 137 if err != nil { 138 return nil, err 139 } 140 filePath = path.Join(home, ".aws", "credentials") 141 } 142 file, err := readFile(filePath) 143 if err != nil { 144 return nil, err 145 } 146 cfg, err := file.GetSection(name) 147 if err != nil { 148 return nil, err 149 } 150 return cfg, nil 151 } 152 153 func readFile(path string) (*ini.File, error) { 154 cfg, err := ini.Load(path) 155 if err != nil { 156 return nil, err 157 } 158 return cfg, nil 159 }