github.com/alexissmirnov/terraform@v0.4.3-0.20150423153700-1ef9731a2f14/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/awslabs/aws-sdk-go/aws"
    11  	"github.com/awslabs/aws-sdk-go/service/autoscaling"
    12  	"github.com/awslabs/aws-sdk-go/service/ec2"
    13  	"github.com/awslabs/aws-sdk-go/service/elb"
    14  	"github.com/awslabs/aws-sdk-go/service/iam"
    15  	"github.com/awslabs/aws-sdk-go/service/rds"
    16  	"github.com/awslabs/aws-sdk-go/service/route53"
    17  	"github.com/awslabs/aws-sdk-go/service/s3"
    18  )
    19  
    20  type Config struct {
    21  	AccessKey string
    22  	SecretKey string
    23  	Token     string
    24  	Region    string
    25  
    26  	AllowedAccountIds   []interface{}
    27  	ForbiddenAccountIds []interface{}
    28  }
    29  
    30  type AWSClient struct {
    31  	ec2conn         *ec2.EC2
    32  	elbconn         *elb.ELB
    33  	autoscalingconn *autoscaling.AutoScaling
    34  	s3conn          *s3.S3
    35  	r53conn         *route53.Route53
    36  	region          string
    37  	rdsconn         *rds.RDS
    38  	iamconn         *iam.IAM
    39  }
    40  
    41  // Client configures and returns a fully initailized AWSClient
    42  func (c *Config) Client() (interface{}, error) {
    43  	var client AWSClient
    44  
    45  	// Get the auth and region. This can fail if keys/regions were not
    46  	// specified and we're attempting to use the environment.
    47  	var errs []error
    48  
    49  	log.Println("[INFO] Building AWS region structure")
    50  	err := c.ValidateRegion()
    51  	if err != nil {
    52  		errs = append(errs, err)
    53  	}
    54  
    55  	if len(errs) == 0 {
    56  		// store AWS region in client struct, for region specific operations such as
    57  		// bucket storage in S3
    58  		client.region = c.Region
    59  
    60  		log.Println("[INFO] Building AWS auth structure")
    61  		creds := aws.DetectCreds(c.AccessKey, c.SecretKey, c.Token)
    62  		awsConfig := &aws.Config{
    63  			Credentials: creds,
    64  			Region:      c.Region,
    65  		}
    66  
    67  		log.Println("[INFO] Initializing ELB connection")
    68  		client.elbconn = elb.New(awsConfig)
    69  
    70  		log.Println("[INFO] Initializing S3 connection")
    71  		client.s3conn = s3.New(awsConfig)
    72  
    73  		log.Println("[INFO] Initializing RDS Connection")
    74  		client.rdsconn = rds.New(awsConfig)
    75  
    76  		log.Println("[INFO] Initializing IAM Connection")
    77  		client.iamconn = iam.New(awsConfig)
    78  
    79  		err := c.ValidateAccountId(client.iamconn)
    80  		if err != nil {
    81  			errs = append(errs, err)
    82  		}
    83  
    84  		log.Println("[INFO] Initializing AutoScaling connection")
    85  		client.autoscalingconn = autoscaling.New(awsConfig)
    86  
    87  		log.Println("[INFO] Initializing EC2 Connection")
    88  		client.ec2conn = ec2.New(awsConfig)
    89  
    90  		// aws-sdk-go uses v4 for signing requests, which requires all global
    91  		// endpoints to use 'us-east-1'.
    92  		// See http://docs.aws.amazon.com/general/latest/gr/sigv4_changes.html
    93  		log.Println("[INFO] Initializing Route 53 connection")
    94  		client.r53conn = route53.New(&aws.Config{
    95  			Credentials: creds,
    96  			Region:      "us-east-1",
    97  		})
    98  
    99  	}
   100  
   101  	if len(errs) > 0 {
   102  		return nil, &multierror.Error{Errors: errs}
   103  	}
   104  
   105  	return &client, nil
   106  }
   107  
   108  // IsValidRegion returns true if the configured region is a valid AWS
   109  // region and false if it's not
   110  func (c *Config) ValidateRegion() error {
   111  	var regions = [11]string{"us-east-1", "us-west-2", "us-west-1", "eu-west-1",
   112  		"eu-central-1", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1",
   113  		"sa-east-1", "cn-north-1", "us-gov-west-1"}
   114  
   115  	for _, valid := range regions {
   116  		if c.Region == valid {
   117  			return nil
   118  		}
   119  	}
   120  	return fmt.Errorf("Not a valid region: %s", c.Region)
   121  }
   122  
   123  func (c *Config) ValidateAccountId(iamconn *iam.IAM) error {
   124  	if c.AllowedAccountIds == nil && c.ForbiddenAccountIds == nil {
   125  		return nil
   126  	}
   127  
   128  	log.Printf("[INFO] Validating account ID")
   129  
   130  	out, err := iamconn.GetUser(nil)
   131  	if err != nil {
   132  		return fmt.Errorf("Failed getting account ID from IAM: %s", err)
   133  	}
   134  
   135  	account_id := strings.Split(*out.User.ARN, ":")[4]
   136  
   137  	if c.ForbiddenAccountIds != nil {
   138  		for _, id := range c.ForbiddenAccountIds {
   139  			if id == account_id {
   140  				return fmt.Errorf("Forbidden account ID (%s)", id)
   141  			}
   142  		}
   143  	}
   144  
   145  	if c.AllowedAccountIds != nil {
   146  		for _, id := range c.AllowedAccountIds {
   147  			if id == account_id {
   148  				return nil
   149  			}
   150  		}
   151  		return fmt.Errorf("Account ID not allowed (%s)", account_id)
   152  	}
   153  
   154  	return nil
   155  }