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