Skip to content

Commit

Permalink
Fixed using authentication provider credentials with `get_aws_account…
Browse files Browse the repository at this point in the history
…_id` (#3243)

* fix: using auth provider creads with get-aws-account-id

* chore: file renaming
  • Loading branch information
levkohimins authored Jul 4, 2024
1 parent fbda728 commit 187f912
Show file tree
Hide file tree
Showing 28 changed files with 119 additions and 138 deletions.
2 changes: 2 additions & 0 deletions aws_helper/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ func CreateAwsSession(config *AwsSessionConfig, terragruntOptions *options.Terra
terragruntOptions.Logger.Debugf("Assuming role %s", terragruntOptions.IAMRoleOptions.RoleARN)
sess.Config.Credentials = getSTSCredentialsFromIAMRoleOptions(sess, terragruntOptions.IAMRoleOptions)
}
} else if creds := getCredentialsFromEnvs(terragruntOptions); creds != nil {
sess.Config.Credentials = creds
}
} else {
sess, err = CreateAwsSessionFromConfig(config, terragruntOptions)
Expand Down
9 changes: 8 additions & 1 deletion cli/commands/terraform/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"time"

"github.com/gruntwork-io/terragrunt/cli/commands/terraform/creds"
"github.com/gruntwork-io/terragrunt/cli/commands/terraform/creds/providers/amazonsts"
"github.com/gruntwork-io/terragrunt/cli/commands/terraform/creds/providers/externalcmd"
"github.com/gruntwork-io/terragrunt/telemetry"

"github.com/gruntwork-io/terragrunt/terraform"
Expand Down Expand Up @@ -88,6 +90,11 @@ func runTerraform(ctx context.Context, terragruntOptions *options.TerragruntOpti
return target.runErrorCallback(terragruntOptions, nil, err)
}

credsGetter := creds.NewGetter()
if err := credsGetter.ObtainAndUpdateEnvIfNecessary(ctx, terragruntOptions, externalcmd.NewProvider(terragruntOptions)); err != nil {
return err
}

terragruntConfig, err := config.ReadTerragruntConfig(terragruntOptions)
if err != nil {
return target.runErrorCallback(terragruntOptions, terragruntConfig, err)
Expand Down Expand Up @@ -119,7 +126,7 @@ func runTerraform(ctx context.Context, terragruntOptions *options.TerragruntOpti
terragruntOptions.OriginalIAMRoleOptions,
)

if err := creds.ObtainCredentialsAndUpdateEnvIfNecessary(ctx, terragruntOptions); err != nil {
if err := credsGetter.ObtainAndUpdateEnvIfNecessary(ctx, terragruntOptions, amazonsts.NewProvider(terragruntOptions)); err != nil {
return err
}

Expand Down
42 changes: 0 additions & 42 deletions cli/commands/terraform/creds/creds.go

This file was deleted.

43 changes: 43 additions & 0 deletions cli/commands/terraform/creds/getter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package creds

import (
"context"

"github.com/gruntwork-io/terragrunt/cli/commands/terraform/creds/providers"
"github.com/gruntwork-io/terragrunt/options"
"golang.org/x/exp/maps"
)

type Getter struct {
obtainedCreds map[string]*providers.Credentials
}

func NewGetter() *Getter {
return &Getter{
obtainedCreds: make(map[string]*providers.Credentials),
}
}

// ObtainAndUpdateEnvIfNecessary obtains credentials through different providers and sets them to `opts.Env`.
func (getter *Getter) ObtainAndUpdateEnvIfNecessary(ctx context.Context, opts *options.TerragruntOptions, authProviders ...providers.Provider) error {
for _, provider := range authProviders {
creds, err := provider.GetCredentials(ctx)
if err != nil {
return err
}
if creds == nil {
continue
}

for providerName, prevCreds := range getter.obtainedCreds {
if prevCreds.Name == creds.Name {
opts.Logger.Warnf("%s credentials obtained using %s are overwritten by credentials obtained using %s.", creds.Name, providerName, provider.Name())
}
}
getter.obtainedCreds[provider.Name()] = creds

maps.Copy(opts.Env, creds.Envs)
}

return nil
}
7 changes: 6 additions & 1 deletion config/dependency.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (

"github.com/gruntwork-io/go-commons/errors"
"github.com/gruntwork-io/terragrunt/cli/commands/terraform/creds"
"github.com/gruntwork-io/terragrunt/cli/commands/terraform/creds/providers/amazonsts"
"github.com/gruntwork-io/terragrunt/cli/commands/terraform/creds/providers/externalcmd"
"github.com/gruntwork-io/terragrunt/codegen"
"github.com/gruntwork-io/terragrunt/config/hclparse"
"github.com/gruntwork-io/terragrunt/options"
Expand Down Expand Up @@ -883,7 +885,10 @@ func setupTerragruntOptionsForBareTerraform(ctx *ParsingContext, workingDir stri
targetTGOptions.IAMRoleOptions = options.MergeIAMRoleOptions(iamRoleOpts, targetTGOptions.OriginalIAMRoleOptions)

// Make sure to assume any roles set by TERRAGRUNT_IAM_ROLE
if err := creds.ObtainCredentialsAndUpdateEnvIfNecessary(ctx, targetTGOptions); err != nil {
if err := creds.NewGetter().ObtainAndUpdateEnvIfNecessary(ctx, targetTGOptions,
externalcmd.NewProvider(targetTGOptions),
amazonsts.NewProvider(targetTGOptions),
); err != nil {
return nil, err
}
return targetTGOptions, nil
Expand Down
9 changes: 0 additions & 9 deletions test/fixture-auth-provider-cmd-remote-state/mock-auth-cmd.sh

This file was deleted.

4 changes: 0 additions & 4 deletions test/fixture-auth-provider-cmd/app1/creds.config

This file was deleted.

15 changes: 0 additions & 15 deletions test/fixture-auth-provider-cmd/app1/test-creds.sh

This file was deleted.

4 changes: 0 additions & 4 deletions test/fixture-auth-provider-cmd/app2/creds.config

This file was deleted.

15 changes: 0 additions & 15 deletions test/fixture-auth-provider-cmd/app2/test-creds.sh

This file was deleted.

4 changes: 0 additions & 4 deletions test/fixture-auth-provider-cmd/app3/creds.config

This file was deleted.

15 changes: 0 additions & 15 deletions test/fixture-auth-provider-cmd/app3/test-creds.sh

This file was deleted.

14 changes: 8 additions & 6 deletions test/fixture-auth-provider-cmd/mock-auth-cmd.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#!/bin/bash -e

set -o pipefail

. ${PWD}/creds.config

json_string=$( jq -n \
--arg access_key_id "$fake_id" \
--arg secret_access_key "$fake_key" \
--arg session_token "$fake_tk" \
--arg tf_var_foo "$tf_var_foo" \
'{awsCredentials: {ACCESS_KEY_ID: $access_key_id, SECRET_ACCESS_KEY: $secret_access_key, SESSION_TOKEN: $session_token}, envs: {TF_VAR_foo: $tf_var_foo}}' )
json_string=$(jq -n \
--arg access_key_id "$access_key_id" \
--arg secret_access_key "$secret_access_key" \
--arg session_token "$session_token" \
--arg tf_var_foo "$tf_var_foo" \
'{awsCredentials: {ACCESS_KEY_ID: $access_key_id, SECRET_ACCESS_KEY: $secret_access_key, SESSION_TOKEN: $session_token}, envs: {TF_VAR_foo: $tf_var_foo}}')

echo $json_string
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
access_key_id=app1_access_key_id
secret_access_key=app1_secret_access_key
session_token=app1_session_token
tf_var_foo=app1-bar
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
terraform {
before_hook "before_hook" {
commands = ["init"]
execute = ["./test-creds.sh"]
}
include {
path = find_in_parent_folders()
}

dependency "app2" {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
access_key_id=app2_access_key_id
secret_access_key=app2_secret_access_key
session_token=app2_session_token
tf_var_foo=app2-bar
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
terraform {
before_hook "before_hook" {
commands = ["init"]
execute = ["./test-creds.sh"]
}
include {
path = find_in_parent_folders()
}

dependency "app3" {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
access_key_id=app3_access_key_id
secret_access_key=app3_secret_access_key
session_token=app3_session_token
tf_var_foo=app3-bar
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include {
path = find_in_parent_folders()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
terraform {
before_hook "before_hook" {
commands = ["init"]
execute = ["./test-creds.sh"]
execute = ["../test-creds.sh"]
}
}
17 changes: 17 additions & 0 deletions test/fixture-auth-provider-cmd/multiple-apps/test-creds.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash -e

set -o pipefail

. ${PWD}/creds.config

if [ "$access_key_id" != "$AWS_ACCESS_KEY_ID" ]; then
exit 1
fi

if [ "$secret_access_key" != "$AWS_SECRET_ACCESS_KEY" ]; then
exit 1
fi

if [ "$session_token" != "$AWS_SESSION_TOKEN" ]; then
exit 1
fi
4 changes: 4 additions & 0 deletions test/fixture-auth-provider-cmd/remote-state/creds.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
access_key_id=__FILL_AWS_ACCESS_KEY_ID__
secret_access_key=__FILL_AWS_SECRET_ACCESS_KEY__
session_token=
tf_var_foo=
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
remote_state {
backend = "s3"
generate = {
path = "backend.tf"
path = "backend-${get_aws_account_id()}.tf"
if_exists = "overwrite_terragrunt"
}
config = {
Expand Down
13 changes: 7 additions & 6 deletions test/integration_serial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -840,18 +840,17 @@ func TestTerragruntProviderCache(t *testing.T) {
}

func TestReadTerragruntAuthProviderCmdRemoteState(t *testing.T) {
cleanupTerraformFolder(t, TEST_FIXTURE_AUTH_PROVIDER_CMD_REMOTE_STATE)
tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_AUTH_PROVIDER_CMD_REMOTE_STATE)
rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_AUTH_PROVIDER_CMD_REMOTE_STATE)
cleanupTerraformFolder(t, TEST_FIXTURE_AUTH_PROVIDER_CMD)
tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_AUTH_PROVIDER_CMD)
rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_AUTH_PROVIDER_CMD, "remote-state")
mockAuthCmd := filepath.Join(tmpEnvPath, TEST_FIXTURE_AUTH_PROVIDER_CMD, "mock-auth-cmd.sh")

s3BucketName := fmt.Sprintf("terragrunt-test-bucket-%s", strings.ToLower(uniqueId()))
defer deleteS3Bucket(t, TERRAFORM_REMOTE_STATE_S3_REGION, s3BucketName)

rootTerragruntConfigPath := util.JoinPath(rootPath, config.DefaultTerragruntConfigPath)
copyTerragruntConfigAndFillPlaceholders(t, rootTerragruntConfigPath, rootTerragruntConfigPath, s3BucketName, "not-used", TERRAFORM_REMOTE_STATE_S3_REGION)

mockAuthCmd := filepath.Join(rootPath, "mock-auth-cmd.sh")

accessKeyID := os.Getenv("AWS_ACCESS_KEY_ID")
secretAccessKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
os.Setenv("AWS_ACCESS_KEY_ID", "")
Expand All @@ -862,7 +861,9 @@ func TestReadTerragruntAuthProviderCmdRemoteState(t *testing.T) {
os.Setenv("AWS_SECRET_ACCESS_KEY", secretAccessKey)
}()

copyAndFillMapPlaceholders(t, mockAuthCmd, mockAuthCmd, map[string]string{
creadsConfig := util.JoinPath(rootPath, "creds.config")

copyAndFillMapPlaceholders(t, creadsConfig, creadsConfig, map[string]string{
"__FILL_AWS_ACCESS_KEY_ID__": accessKeyID,
"__FILL_AWS_SECRET_ACCESS_KEY__": secretAccessKey,
})
Expand Down
7 changes: 3 additions & 4 deletions test/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ const (
TEST_FIXTURE_OUT_DIR = "fixture-out-dir"
TEST_FIXTURE_SOPS_ERRORS = "fixture-sops-errors"
TEST_FIXTURE_AUTH_PROVIDER_CMD = "fixture-auth-provider-cmd"
TEST_FIXTURE_AUTH_PROVIDER_CMD_REMOTE_STATE = "fixture-auth-provider-cmd-remote-state"
TERRAFORM_BINARY = "terraform"
TOFU_BINARY = "tofu"
TERRAFORM_FOLDER = ".terraform"
Expand Down Expand Up @@ -4132,11 +4131,11 @@ func TestReadTerragruntAuthProviderCmd(t *testing.T) {

cleanupTerraformFolder(t, TEST_FIXTURE_AUTH_PROVIDER_CMD)
tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_AUTH_PROVIDER_CMD)
rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_AUTH_PROVIDER_CMD)
rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_AUTH_PROVIDER_CMD, "multiple-apps")
appPath := util.JoinPath(rootPath, "app1")
mockAuthCmd := filepath.Join(rootPath, "mock-auth-cmd.sh")
mockAuthCmd := filepath.Join(tmpEnvPath, TEST_FIXTURE_AUTH_PROVIDER_CMD, "mock-auth-cmd.sh")

runTerragrunt(t, fmt.Sprintf("terragrunt run-all apply -auto-approve --terragrunt-non-interactive --terragrunt-working-dir %s --terragrunt-auth-provider-cmd %s", rootPath, mockAuthCmd))
runTerragrunt(t, fmt.Sprintf(`terragrunt run-all apply -auto-approve --terragrunt-non-interactive --terragrunt-working-dir %s --terragrunt-auth-provider-cmd %s`, rootPath, mockAuthCmd))

stdout, _, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt output -json --terragrunt-working-dir %s --terragrunt-auth-provider-cmd %s", appPath, mockAuthCmd))
assert.NoError(t, err)
Expand Down

0 comments on commit 187f912

Please sign in to comment.