Skip to content

Commit

Permalink
Improve AWS configuration (#165)
Browse files Browse the repository at this point in the history
* Improve AWS configuration

Add a warning if a user is using both AWS_PROFILE and AWS_ACCESS_KEY_ID at the same time.

Check the default expiration time for the session and issue a warning if the configuration is less than 1 hour. go library use 15 minutes by default when assuming a role and users must extend that  duration by configuring properly their session duration.

Set the AWS_REGION variable when freezing the default credentials. Otherwise, the region specified on the profile is ignored.

Avoid checking if there is an AWS configuration multiple times.

Be consistent when evaluating the AWS profile. By calling getAWSSession with and without parameter, that causes ignoring the argument provided profile on the second call.

Provide a backup path to auto update. Otherwise, the replacement of the current executable prevent it to relaunch itself. DT-3322

* Apply go mod tidy
  • Loading branch information
jocgir authored Dec 3, 2020
1 parent 811abe9 commit e7b0667
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 52 deletions.
63 changes: 45 additions & 18 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,22 +148,46 @@ func (config TGFConfig) String() string {
return string(bytes)
}

func (config *TGFConfig) getAwsSession() (*session.Session, error) {
return session.NewSessionWithOptions(session.Options{
Profile: config.tgf.AwsProfile,
SharedConfigState: session.SharedConfigEnable,
AssumeRoleTokenProvider: stscreds.StdinTokenProvider,
})
}

// InitAWS tries to open an AWS session and init AWS environment variable on success
func (config *TGFConfig) InitAWS(profile string) error {
sess, err := getAwsSession(profile)
func (config *TGFConfig) InitAWS() error {
if config.tgf.AwsProfile == "" && os.Getenv("AWS_ACCESS_KEY_ID") != "" && os.Getenv("AWS_PROFILE") != "" {
log.Warning("You set both AWS_ACCESS_KEY_ID and AWS_PROFILE, AWS_PROFILE will be ignored")
}
session, err := config.getAwsSession()
if err != nil {
return err
}
creds, err := sess.Config.Credentials.Get()
creds, err := session.Config.Credentials.Get()
if err != nil {
return err
}
expiration, _ := session.Config.Credentials.ExpiresAt()
if duration := time.Until(expiration).Round(time.Minute); duration > 0 && duration < 55*time.Minute {
var profile string
if profile = config.tgf.AwsProfile; profile == "" {
if profile = os.Getenv("AWS_PROFILE"); profile == "" {
profile = "default"
}
}
log.Warningf("Your AWS configuration is set to expire your session in %v", duration)
log.Warningf(color.WhiteString("You should consider defining %s in your AWS config profile %s"),
color.HiBlueString("duration_seconds = 14400"), color.HiBlueString(profile))
}
os.Unsetenv("AWS_PROFILE")
os.Unsetenv("AWS_DEFAULT_PROFILE")
for key, value := range map[string]string{
"AWS_ACCESS_KEY_ID": creds.AccessKeyID,
"AWS_SECRET_ACCESS_KEY": creds.SecretAccessKey,
"AWS_SESSION_TOKEN": creds.SessionToken,
"AWS_REGION": *session.Config.Region,
} {
os.Setenv(key, value)
config.Environment[key] = value
Expand All @@ -190,7 +214,7 @@ func (config *TGFConfig) setDefaultValues() {

// Fetch SSM configs
if config.awsConfigExist() {
if err := config.InitAWS(""); err != nil {
if err := config.InitAWS(); err != nil {
log.Errorf("Unable to authentify to AWS: %v\nPararameter store is ignored\n", err)
} else {
if app.ConfigLocation == "" {
Expand Down Expand Up @@ -387,14 +411,14 @@ func (config *TGFConfig) ParseAliases() {
}

func (config *TGFConfig) readSSMParameterStore(ssmParameterFolder string) map[string]string {
log.Debugln("Reading configuration from SSM", ssmParameterFolder)
values := make(map[string]string)
sess, err := getAwsSession("")
session, err := config.getAwsSession()
log.Debugf("Reading configuration from SSM %s in %s", ssmParameterFolder, *session.Config.Region)
if err != nil {
log.Warningf("Caught an error while creating an AWS session: %v", err)
return values
}
svc := ssm.New(sess)
svc := ssm.New(session)
response, err := svc.GetParametersByPath(&ssm.GetParametersByPathInput{
Path: aws.String(ssmParameterFolder),
Recursive: aws.Bool(true),
Expand Down Expand Up @@ -478,7 +502,11 @@ func parseSsmConfig(parameterValues map[string]string) string {
//
// We call this function before trying to init an AWS session. This avoid trying to init a session in a non AWS context
// and having to wait for metadata resolution or generating an error.
func (config TGFConfig) awsConfigExist() bool {
func (config TGFConfig) awsConfigExist() (result bool) {
if cachedAWSConfigExistCheck != nil {
return *cachedAWSConfigExistCheck
}
defer func() { cachedAWSConfigExistCheck = &result }()
app := config.tgf
if !app.UseAWS {
log.Debugln("Not trying to read the config from AWS. It is disabled")
Expand Down Expand Up @@ -515,6 +543,8 @@ func (config TGFConfig) awsConfigExist() bool {
return awsFolderExists
}

var cachedAWSConfigExistCheck *bool

// Return the list of configuration files found from the current working directory up to the root folder
func (config TGFConfig) findConfigFiles(folder string) (result []string) {
app := config.tgf
Expand Down Expand Up @@ -679,12 +709,17 @@ func (config *TGFConfig) getTgfFile(url string) (tgfFile io.ReadCloser, err erro

// DoUpdate fetch the executable from the link, unzip it and replace it with the current
func (config *TGFConfig) DoUpdate(url string) (err error) {
tgfFile, err := config.getTgfFile(url)
savePath, err := ioutil.TempFile("", "tgf.previous-version")
if err != nil {
return
}
err = update.Apply(tgfFile, update.Options{})

tgfFile, err := config.getTgfFile(url)
if err != nil {
return
}

if err = update.Apply(tgfFile, update.Options{OldSavePath: savePath.Name()}); err != nil {
if err := update.RollbackError(err); err != nil {
log.Errorln("Failed to rollback from bad update:", err)
}
Expand All @@ -701,11 +736,3 @@ func (config *TGFConfig) GetLastRefresh(autoUpdateFile string) time.Duration {
func (config *TGFConfig) SetLastRefresh(autoUpdateFile string) {
touchImageRefresh(autoUpdateFile)
}

func getAwsSession(profile string) (*session.Session, error) {
return session.NewSessionWithOptions(session.Options{
Profile: profile,
SharedConfigState: session.SharedConfigEnable,
AssumeRoleTokenProvider: stscreds.StdinTokenProvider,
})
}
5 changes: 0 additions & 5 deletions config_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import (
func (config *TGFConfig) Run() int {
app := config.tgf

// If AWS profile is supplied, we freeze the current session
if app.AwsProfile != "" {
must(config.InitAWS(app.AwsProfile))
}

if app.Image != "" {
config.Image = app.Image
config.RecommendedImageVersion = ""
Expand Down
2 changes: 2 additions & 0 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ func TestCheckVersionRange(t *testing.T) {
}

func TestSetConfigDefaultValues(t *testing.T) {
// We must reset the cached AWS config check since it could have been modified by another test
cachedAWSConfigExistCheck = nil
tempDir, _ := filepath.EvalSymlinks(must(ioutil.TempDir("", "TestGetConfig")).(string))
currentDir, _ := os.Getwd()
assert.NoError(t, os.Chdir(tempDir))
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ module github.com/coveooss/tgf
go 1.13

require (
github.com/Microsoft/go-winio v0.4.14 // indirect
github.com/aws/aws-sdk-go v1.35.19
github.com/Microsoft/go-winio v0.4.15 // indirect
github.com/aws/aws-sdk-go v1.36.0
github.com/blang/semver v3.5.1+incompatible
github.com/coveooss/gotemplate/v3 v3.5.2
github.com/coveooss/gotemplate/v3 v3.6.0
github.com/coveooss/multilogger v0.5.2
github.com/coveord/kingpin/v2 v2.3.1
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/docker v1.13.1
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/fatih/color v1.10.0
github.com/hashicorp/go-getter v1.5.0
github.com/hashicorp/go-getter v1.5.1
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/sirupsen/logrus v1.7.0
github.com/stretchr/testify v1.6.1
gopkg.in/yaml.v2 v2.3.0
gopkg.in/yaml.v2 v2.4.0
)
Loading

0 comments on commit e7b0667

Please sign in to comment.