diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index d9e076841..9c6599258 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "strings" "github.com/hashicorp/terraform/helper/multierror" @@ -21,6 +22,9 @@ type Config struct { SecretKey string Token string Region string + + AllowedAccountIds []interface{} + ForbiddenAccountIds []interface{} } type AWSClient struct { @@ -71,6 +75,12 @@ func (c *Config) Client() (interface{}, error) { log.Println("[INFO] Initializing IAM Connection") client.iamconn = iam.New(awsConfig) + + err := c.ValidateAccountId(client.iamconn) + if err != nil { + errs = append(errs, err) + } + log.Println("[INFO] Initializing AutoScaling connection") client.autoscalingconn = autoscaling.New(awsConfig) @@ -109,3 +119,37 @@ func (c *Config) ValidateRegion() error { } return fmt.Errorf("Not a valid region: %s", c.Region) } + +func (c *Config) ValidateAccountId(iamconn *iam.IAM) error { + if c.AllowedAccountIds == nil && c.ForbiddenAccountIds == nil { + return nil + } + + log.Printf("[INFO] Validating account ID") + + out, err := iamconn.GetUser(nil) + if err != nil { + return fmt.Errorf("Failed getting account ID from IAM: %s", err) + } + + account_id := strings.Split(*out.User.ARN, ":")[4] + + if c.ForbiddenAccountIds != nil { + for _, id := range c.ForbiddenAccountIds { + if id == account_id { + return fmt.Errorf("Forbidden account ID (%s)", id) + } + } + } + + if c.AllowedAccountIds != nil { + for _, id := range c.AllowedAccountIds { + if id == account_id { + return nil + } + } + return fmt.Errorf("Account ID not allowed (%s)", account_id) + } + + return nil +} diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 50596512e..75f0fda35 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -1,6 +1,7 @@ package aws import ( + "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/terraform" ) @@ -42,6 +43,26 @@ func Provider() terraform.ResourceProvider { Description: descriptions["region"], InputDefault: "us-east-1", }, + + "allowed_account_ids": &schema.Schema{ + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + ConflictsWith: []string{"forbidden_account_ids"}, + Set: func(v interface{}) int { + return hashcode.String(v.(string)) + }, + }, + + "forbidden_account_ids": &schema.Schema{ + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + ConflictsWith: []string{"allowed_account_ids"}, + Set: func(v interface{}) int { + return hashcode.String(v.(string)) + }, + }, }, ResourcesMap: map[string]*schema.Resource{ @@ -97,5 +118,13 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { Region: d.Get("region").(string), } + if v, ok := d.GetOk("allowed_account_ids"); ok { + config.AllowedAccountIds = v.(*schema.Set).List() + } + + if v, ok := d.GetOk("forbidden_account_ids"); ok { + config.ForbiddenAccountIds = v.(*schema.Set).List() + } + return config.Client() } diff --git a/helper/schema/schema.go b/helper/schema/schema.go index 04b242bbe..fd53aa603 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -384,6 +384,8 @@ func (m schemaMap) Input( fallthrough case TypeFloat: fallthrough + case TypeSet: + continue case TypeString: value, err = m.inputString(input, k, v) default: diff --git a/website/source/docs/providers/aws/index.html.markdown b/website/source/docs/providers/aws/index.html.markdown index dc5fe92b9..57619f11f 100644 --- a/website/source/docs/providers/aws/index.html.markdown +++ b/website/source/docs/providers/aws/index.html.markdown @@ -22,6 +22,9 @@ provider "aws" { access_key = "${var.aws_access_key}" secret_key = "${var.aws_secret_key}" region = "us-east-1" + + # Not run this in live account + forbidden_account_ids = ["1234567890"] } # Create a web server @@ -43,5 +46,13 @@ The following arguments are supported in the `provider` block: * `region` - (Required) This is the AWS region. It must be provided, but it can also be sourced from the `AWS_DEFAULT_REGION` environment variables. +* `allowed_account_ids` - (Optional) List of allowed AWS account IDs (whitelist) + to prevent you mistakenly using a wrong one (and end up destroying live environment). + Conflicts with `forbidden_account_ids`. + +* `forbidden_account_ids` - (Optional) List of forbidden AWS account IDs (blacklist) + to prevent you mistakenly using a wrong one (and end up destroying live environment). + Conflicts with `allowed_account_ids`. + In addition to the above parameters, the `AWS_SECURITY_TOKEN` environmental variable can be set to set an MFA token.