github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/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  }