github.com/rothwerx/packer@v0.9.0/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 svc := sts.New(session.New(), srcCfg) 65 res, err := svc.AssumeRole(c.AssumeRoleInput) 66 if err != nil { 67 return nil, err 68 } 69 return credentials.NewStaticCredentials( 70 *res.Credentials.AccessKeyId, 71 *res.Credentials.SecretAccessKey, 72 *res.Credentials.SessionToken, 73 ), nil 74 } 75 76 // Sets params in the struct based on the file section 77 func (c *CLIConfig) Prepare(name string) error { 78 var err error 79 c.ProfileName = name 80 c.profileCfg, err = configFromName(c.ProfileName) 81 if err != nil { 82 return err 83 } 84 c.SourceProfile = c.profileCfg.Key("source_profile").Value() 85 if c.SourceProfile == "" { 86 c.SourceProfile = c.ProfileName 87 } 88 c.profileCred, err = credsFromName(c.SourceProfile) 89 if err != nil { 90 return err 91 } 92 return nil 93 } 94 95 func (c *CLIConfig) getSessionName(rawName string) (string, error) { 96 if rawName == "" { 97 name := "packer-" 98 host, err := os.Hostname() 99 if err != nil { 100 return name, err 101 } 102 return fmt.Sprintf("%s%s", name, host), nil 103 } else { 104 return rawName, nil 105 } 106 } 107 108 func configFromName(name string) (*ini.Section, error) { 109 filePath := os.Getenv("AWS_CONFIG_FILE") 110 if filePath == "" { 111 home, err := homedir.Dir() 112 if err != nil { 113 return nil, err 114 } 115 filePath = path.Join(home, ".aws", "config") 116 } 117 file, err := readFile(filePath) 118 if err != nil { 119 return nil, err 120 } 121 profileName := fmt.Sprintf("profile %s", name) 122 cfg, err := file.GetSection(profileName) 123 if err != nil { 124 return nil, err 125 } 126 return cfg, nil 127 } 128 129 func credsFromName(name string) (*ini.Section, error) { 130 filePath := os.Getenv("AWS_SHARED_CREDENTIALS_FILE") 131 if filePath == "" { 132 home, err := homedir.Dir() 133 if err != nil { 134 return nil, err 135 } 136 filePath = path.Join(home, ".aws", "credentials") 137 } 138 file, err := readFile(filePath) 139 if err != nil { 140 return nil, err 141 } 142 cfg, err := file.GetSection(name) 143 if err != nil { 144 return nil, err 145 } 146 return cfg, nil 147 } 148 149 func readFile(path string) (*ini.File, error) { 150 cfg, err := ini.Load(path) 151 if err != nil { 152 return nil, err 153 } 154 return cfg, nil 155 }