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