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  }