github.com/ggiamarchi/terraform@v0.3.7-0.20150607194748-ed2a66a46a71/builtin/providers/aws/config.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 8 "github.com/hashicorp/terraform/helper/multierror" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/aws/credentials" 12 "github.com/aws/aws-sdk-go/service/autoscaling" 13 "github.com/aws/aws-sdk-go/service/ec2" 14 "github.com/aws/aws-sdk-go/service/ecs" 15 "github.com/aws/aws-sdk-go/service/elasticache" 16 "github.com/aws/aws-sdk-go/service/elb" 17 "github.com/aws/aws-sdk-go/service/iam" 18 "github.com/aws/aws-sdk-go/service/kinesis" 19 "github.com/aws/aws-sdk-go/service/rds" 20 "github.com/aws/aws-sdk-go/service/route53" 21 "github.com/aws/aws-sdk-go/service/s3" 22 "github.com/aws/aws-sdk-go/service/sns" 23 "github.com/aws/aws-sdk-go/service/sqs" 24 ) 25 26 type Config struct { 27 AccessKey string 28 SecretKey string 29 Token string 30 Region string 31 MaxRetries int 32 33 AllowedAccountIds []interface{} 34 ForbiddenAccountIds []interface{} 35 } 36 37 type AWSClient struct { 38 ec2conn *ec2.EC2 39 ecsconn *ecs.ECS 40 elbconn *elb.ELB 41 autoscalingconn *autoscaling.AutoScaling 42 s3conn *s3.S3 43 sqsconn *sqs.SQS 44 snsconn *sns.SNS 45 r53conn *route53.Route53 46 region string 47 rdsconn *rds.RDS 48 iamconn *iam.IAM 49 kinesisconn *kinesis.Kinesis 50 elasticacheconn *elasticache.ElastiCache 51 } 52 53 // Client configures and returns a fully initailized AWSClient 54 func (c *Config) Client() (interface{}, error) { 55 var client AWSClient 56 57 // Get the auth and region. This can fail if keys/regions were not 58 // specified and we're attempting to use the environment. 59 var errs []error 60 61 log.Println("[INFO] Building AWS region structure") 62 err := c.ValidateRegion() 63 if err != nil { 64 errs = append(errs, err) 65 } 66 67 if len(errs) == 0 { 68 // store AWS region in client struct, for region specific operations such as 69 // bucket storage in S3 70 client.region = c.Region 71 72 log.Println("[INFO] Building AWS auth structure") 73 creds := credentials.NewChainCredentials([]credentials.Provider{ 74 &credentials.StaticProvider{Value: credentials.Value{ 75 AccessKeyID: c.AccessKey, 76 SecretAccessKey: c.SecretKey, 77 SessionToken: c.Token, 78 }}, 79 &credentials.EnvProvider{}, 80 &credentials.SharedCredentialsProvider{Filename: "", Profile: ""}, 81 &credentials.EC2RoleProvider{}, 82 }) 83 awsConfig := &aws.Config{ 84 Credentials: creds, 85 Region: c.Region, 86 MaxRetries: c.MaxRetries, 87 } 88 89 log.Println("[INFO] Initializing ELB connection") 90 client.elbconn = elb.New(awsConfig) 91 92 log.Println("[INFO] Initializing S3 connection") 93 client.s3conn = s3.New(awsConfig) 94 95 log.Println("[INFO] Initializing SQS connection") 96 client.sqsconn = sqs.New(awsConfig) 97 98 log.Println("[INFO] Initializing SNS connection") 99 client.snsconn = sns.New(awsConfig) 100 101 log.Println("[INFO] Initializing RDS Connection") 102 client.rdsconn = rds.New(awsConfig) 103 104 log.Println("[INFO] Initializing IAM Connection") 105 client.iamconn = iam.New(awsConfig) 106 107 log.Println("[INFO] Initializing Kinesis Connection") 108 client.kinesisconn = kinesis.New(awsConfig) 109 110 err := c.ValidateAccountId(client.iamconn) 111 if err != nil { 112 errs = append(errs, err) 113 } 114 115 log.Println("[INFO] Initializing AutoScaling connection") 116 client.autoscalingconn = autoscaling.New(awsConfig) 117 118 log.Println("[INFO] Initializing EC2 Connection") 119 client.ec2conn = ec2.New(awsConfig) 120 121 log.Println("[INFO] Initializing ECS Connection") 122 client.ecsconn = ecs.New(awsConfig) 123 124 // aws-sdk-go uses v4 for signing requests, which requires all global 125 // endpoints to use 'us-east-1'. 126 // See http://docs.aws.amazon.com/general/latest/gr/sigv4_changes.html 127 log.Println("[INFO] Initializing Route 53 connection") 128 client.r53conn = route53.New(&aws.Config{ 129 Credentials: creds, 130 Region: "us-east-1", 131 MaxRetries: c.MaxRetries, 132 }) 133 134 log.Println("[INFO] Initializing Elasticache Connection") 135 client.elasticacheconn = elasticache.New(awsConfig) 136 } 137 138 if len(errs) > 0 { 139 return nil, &multierror.Error{Errors: errs} 140 } 141 142 return &client, nil 143 } 144 145 // ValidateRegion returns an error if the configured region is not a 146 // valid aws region and nil otherwise. 147 func (c *Config) ValidateRegion() error { 148 var regions = [11]string{"us-east-1", "us-west-2", "us-west-1", "eu-west-1", 149 "eu-central-1", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1", 150 "sa-east-1", "cn-north-1", "us-gov-west-1"} 151 152 for _, valid := range regions { 153 if c.Region == valid { 154 return nil 155 } 156 } 157 return fmt.Errorf("Not a valid region: %s", c.Region) 158 } 159 160 // ValidateAccountId returns a context-specific error if the configured account 161 // id is explicitly forbidden or not authorised; and nil if it is authorised. 162 func (c *Config) ValidateAccountId(iamconn *iam.IAM) error { 163 if c.AllowedAccountIds == nil && c.ForbiddenAccountIds == nil { 164 return nil 165 } 166 167 log.Printf("[INFO] Validating account ID") 168 169 out, err := iamconn.GetUser(nil) 170 if err != nil { 171 return fmt.Errorf("Failed getting account ID from IAM: %s", err) 172 } 173 174 account_id := strings.Split(*out.User.ARN, ":")[4] 175 176 if c.ForbiddenAccountIds != nil { 177 for _, id := range c.ForbiddenAccountIds { 178 if id == account_id { 179 return fmt.Errorf("Forbidden account ID (%s)", id) 180 } 181 } 182 } 183 184 if c.AllowedAccountIds != nil { 185 for _, id := range c.AllowedAccountIds { 186 if id == account_id { 187 return nil 188 } 189 } 190 return fmt.Errorf("Account ID not allowed (%s)", account_id) 191 } 192 193 return nil 194 }