Skip to content

Commit

Permalink
Merge pull request #360 from wata727/shared_credentials_file
Browse files Browse the repository at this point in the history
Allow settings shared credentials file path
  • Loading branch information
wata727 authored Jul 15, 2019
2 parents 31a29c5 + b9a3b1c commit 4f7a785
Show file tree
Hide file tree
Showing 208 changed files with 990 additions and 249 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Application Options:
--aws-access-key=ACCESS_KEY AWS access key used in deep check mode
--aws-secret-key=SECRET_KEY AWS secret key used in deep check mode
--aws-profile=PROFILE AWS shared credential profile name used in deep check mode
--aws-creds-file=FILE AWS shared credentials file path used in deep checking
--aws-region=REGION AWS region used in deep check mode
--force Return zero exit status even if issues found
-q, --quiet Do not output any message when no issues are found (default format only)
Expand Down
35 changes: 24 additions & 11 deletions client/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,18 @@ type AwsCredentials struct {
AccessKey string
SecretKey string
Profile string
CredsFile string
Region string
}

// NewAwsClient returns new AwsClient with configured session
func NewAwsClient(creds AwsCredentials) *AwsClient {
func NewAwsClient(creds AwsCredentials) (*AwsClient, error) {
log.Print("[INFO] Initialize AWS Client")

s := newAwsSession(creds)
s, err := newAwsSession(creds)
if err != nil {
return nil, err
}

return &AwsClient{
IAM: iam.New(s),
Expand All @@ -65,11 +69,11 @@ func NewAwsClient(creds AwsCredentials) *AwsClient {
ELB: elb.New(s),
ELBV2: elbv2.New(s),
ECS: ecs.New(s),
}
}, nil
}

// newAwsSession returns a session necessary for initialization of the AWS SDK
func newAwsSession(creds AwsCredentials) *session.Session {
func newAwsSession(creds AwsCredentials) (*session.Session, error) {
s := session.New()

if creds.Region != "" {
Expand All @@ -79,14 +83,23 @@ func newAwsSession(creds AwsCredentials) *session.Session {
})
}
if creds.Profile != "" && creds.Region != "" {
log.Printf("[INFO] Set AWS shared credentials")
path, err := homedir.Expand("~/.aws/credentials")
if err != nil {
// Maybe this is bug
panic(err)
var credsFile string
var err error
if creds.CredsFile != "" {
credsFile, err = homedir.Expand(creds.CredsFile)
if err != nil {
return nil, err
}
} else {
credsFile, err = homedir.Expand("~/.aws/credentials")
if err != nil {
// Maybe this is bug
panic(err)
}
}
log.Printf("[INFO] Set AWS shared credentials: %s", credsFile)
s = session.New(&aws.Config{
Credentials: credentials.NewSharedCredentials(path, creds.Profile),
Credentials: credentials.NewSharedCredentials(credsFile, creds.Profile),
Region: aws.String(creds.Region),
})
}
Expand All @@ -98,5 +111,5 @@ func newAwsSession(creds AwsCredentials) *session.Session {
})
}

return s
return s, nil
}
18 changes: 17 additions & 1 deletion client/aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func Test_newAwsSession(t *testing.T) {
Region *string
}
path, _ := homedir.Expand("~/.aws/credentials")
credPath, _ := homedir.Expand("~/.aws/creds")

cases := []struct {
Name string
Expand Down Expand Up @@ -44,10 +45,25 @@ func Test_newAwsSession(t *testing.T) {
Region: aws.String("us-east-1"),
},
},
{
Name: "shared credentials path",
Creds: AwsCredentials{
Profile: "default",
CredsFile: "~/.aws/creds",
Region: "us-east-1",
},
Expected: Result{
Credentials: credentials.NewSharedCredentials(credPath, "default"),
Region: aws.String("us-east-1"),
},
},
}

for _, tc := range cases {
s := newAwsSession(tc.Creds)
s, err := newAwsSession(tc.Creds)
if err != nil {
t.Fatalf("Failed `%s` test: Unexpected error occurred: %s", tc.Name, err)
}
if !reflect.DeepEqual(tc.Expected.Credentials, s.Config.Credentials) {
t.Fatalf("Failed `%s` test: expected credentials are `%#v`, but get `%#v`", tc.Name, tc.Expected.Credentials, s.Config.Credentials)
}
Expand Down
6 changes: 5 additions & 1 deletion cmd/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ func (cli *CLI) Run(args []string) int {
variables = append(variables, cliVars)

// Check configurations via Runner
runner := tflint.NewRunner(cfg, annotations, configs, variables...)
runner, err := tflint.NewRunner(cfg, annotations, configs, variables...)
if err != nil {
cli.printError(fmt.Errorf("Failed to initialize a runner: %s", err))
return ExitCodeError
}
runners, err := tflint.NewModuleRunners(runner)
if err != nil {
cli.printError(fmt.Errorf("Failed to prepare rule checking: %s", err))
Expand Down
2 changes: 2 additions & 0 deletions cmd/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Options struct {
AwsAccessKey string `long:"aws-access-key" description:"AWS access key used in deep check mode" value-name:"ACCESS_KEY"`
AwsSecretKey string `long:"aws-secret-key" description:"AWS secret key used in deep check mode" value-name:"SECRET_KEY"`
AwsProfile string `long:"aws-profile" description:"AWS shared credential profile name used in deep check mode" value-name:"PROFILE"`
AwsCredsFile string `long:"aws-creds-file" description:"AWS shared credentials file path used in deep checking" value-name:"FILE"`
AwsRegion string `long:"aws-region" description:"AWS region used in deep check mode" value-name:"REGION"`
Force bool `long:"force" description:"Return zero exit status even if issues found"`
Quiet bool `short:"q" long:"quiet" description:"Do not output any message when no issues are found (default format only)"`
Expand Down Expand Up @@ -67,6 +68,7 @@ func (opts *Options) toConfig() *tflint.Config {
AccessKey: opts.AwsAccessKey,
SecretKey: opts.AwsSecretKey,
Profile: opts.AwsProfile,
CredsFile: opts.AwsCredsFile,
Region: opts.AwsRegion,
},
IgnoreModule: ignoreModule,
Expand Down
19 changes: 19 additions & 0 deletions cmd/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,25 @@ func Test_toConfig(t *testing.T) {
Rules: map[string]*tflint.RuleConfig{},
},
},
{
Name: "AWS shared credentials in another file",
Command: "./tflint --aws-creds-file ~/.aws/myapp --aws-profile production --aws-region us-east-1",
Expected: &tflint.Config{
Module: false,
DeepCheck: false,
Force: false,
AwsCredentials: client.AwsCredentials{
CredsFile: "~/.aws/myapp",
Profile: "production",
Region: "us-east-1",
},
IgnoreModule: map[string]bool{},
IgnoreRule: map[string]bool{},
Varfile: []string{},
Variables: []string{},
Rules: map[string]*tflint.RuleConfig{},
},
},
{
Name: "--ignore-module",
Command: "./tflint --ignore-module module1,module2",
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Return zero exit status even if issues found. TFLint returns non-zero exit statu

## `aws_credentials`

CLI flag: `--aws-access-key`, `--aws-secret-key`, `--aws-profile` and `--aws-region`
CLI flag: `--aws-access-key`, `--aws-secret-key`, `--aws-profile`, `--aws-creds-file` and `--aws-region`

Configure AWS service crendetials. See [Credentials](credentials.md).

Expand Down
9 changes: 5 additions & 4 deletions docs/guides/credentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,18 @@ config {

## Shared Credentials

If you have [shared credentials](https://aws.amazon.com/jp/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/), you can pass the profile name. However, only `~/.aws/credentials` is supported as a credential location.
If you have [shared credentials](https://aws.amazon.com/jp/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/), you can pass a profile name and credentials file path. If omitted, these will be `default` and `~/.aws/credentials`.

```
$ tflint --aws-profile AWS_PROFILE --aws-region us-east-1
$ tflint --aws-profile AWS_PROFILE --aws-region us-east-1 --aws-creds-file ~/.aws/myapp
```

```hcl
config {
aws_credentials = {
profile = "AWS_PROFILE"
region = "us-east-1"
profile = "AWS_PROFILE"
region = "us-east-1"
shared_credentials_file = "~/.aws/myapp"
}
}
```
Expand Down
10 changes: 8 additions & 2 deletions rules/awsrules/aws_alb_invalid_security_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,10 @@ resource "aws_alb" "balancer" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsALBInvalidSecurityGroupRule()

mock := client.NewMockEC2API(ctrl)
Expand Down Expand Up @@ -239,7 +242,10 @@ resource "aws_alb" "balancer" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsALBInvalidSecurityGroupRule()

mock := client.NewMockEC2API(ctrl)
Expand Down
5 changes: 4 additions & 1 deletion rules/awsrules/aws_alb_invalid_subnet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ resource "aws_alb" "balancer" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsALBInvalidSubnetRule()

mock := client.NewMockEC2API(ctrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ resource "aws_db_instance" "db" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsDBInstanceDefaultParameterGroupRule()

if err = rule.Check(runner); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ resource "aws_db_instance" "mysql" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsDBInstanceInvalidDBSubnetGroupRule()

mock := client.NewMockRDSAPI(ctrl)
Expand Down
5 changes: 4 additions & 1 deletion rules/awsrules/aws_db_instance_invalid_option_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ resource "aws_db_instance" "mysql" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsDBInstanceInvalidOptionGroupRule()

mock := client.NewMockRDSAPI(ctrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ resource "aws_db_instance" "mysql" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsDBInstanceInvalidParameterGroupRule()

mock := client.NewMockRDSAPI(ctrl)
Expand Down
5 changes: 4 additions & 1 deletion rules/awsrules/aws_db_instance_invalid_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ resource "aws_db_instance" "mysql" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsDBInstanceInvalidTypeRule()

if err = rule.Check(runner); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ resource "aws_db_instance" "mysql" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsDBInstanceInvalidVPCSecurityGroupRule()

mock := client.NewMockEC2API(ctrl)
Expand Down
5 changes: 4 additions & 1 deletion rules/awsrules/aws_db_instance_previous_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ resource "aws_db_instance" "mysql" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsDBInstancePreviousTypeRule()

if err = rule.Check(runner); err != nil {
Expand Down
5 changes: 4 additions & 1 deletion rules/awsrules/aws_db_instance_readable_password_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ resource "aws_db_instance" "mysql" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsDBInstanceReadablePasswordRule()

if err = rule.Check(runner); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ resource "aws_elasticache_cluster" "cache" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsElastiCacheClusterDefaultParameterGroupRule()

if err = rule.Check(runner); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ resource "aws_elasticache_cluster" "redis" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsElastiCacheClusterInvalidParameterGroupRule()

mock := client.NewMockElastiCacheAPI(ctrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ resource "aws_elasticache_cluster" "redis" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsElastiCacheClusterInvalidSecurityGroupRule()

mock := client.NewMockEC2API(ctrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ resource "aws_elasticache_cluster" "redis" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsElastiCacheClusterInvalidSubnetGroupRule()

mock := client.NewMockElastiCacheAPI(ctrl)
Expand Down
5 changes: 4 additions & 1 deletion rules/awsrules/aws_elasticache_cluster_invalid_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ resource "aws_elasticache_cluster" "redis" {
t.Fatal(tfdiags)
}

runner := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
runner, err := tflint.NewRunner(tflint.EmptyConfig(), map[string]tflint.Annotations{}, cfg, map[string]*terraform.InputValue{})
if err != nil {
t.Fatal(err)
}
rule := NewAwsElastiCacheClusterInvalidTypeRule()

if err = rule.Check(runner); err != nil {
Expand Down
Loading

0 comments on commit 4f7a785

Please sign in to comment.