diff --git a/builtin/providers/aws/data_source_aws_ip_ranges.go b/builtin/providers/aws/data_source_aws_ip_ranges.go new file mode 100644 index 0000000000..c530d981df --- /dev/null +++ b/builtin/providers/aws/data_source_aws_ip_ranges.go @@ -0,0 +1,128 @@ +package aws + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "sort" + "strings" + "time" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/terraform/helper/schema" +) + +type dataSourceAwsIPRangesResult struct { + CreateDate string + Prefixes []dataSourceAwsIPRangesPrefix + SyncToken string +} + +type dataSourceAwsIPRangesPrefix struct { + IpPrefix string `json:"ip_prefix"` + Region string + Service string +} + +func dataSourceAwsIPRanges() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsIPRangesRead, + + Schema: map[string]*schema.Schema{ + "blocks": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "create_date": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "regions": &schema.Schema{ + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "services": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "sync_token": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceAwsIPRangesRead(d *schema.ResourceData, meta interface{}) error { + + conn := cleanhttp.DefaultClient() + + log.Printf("[DEBUG] Reading IP ranges") + d.SetId(time.Now().UTC().String()) + + res, err := conn.Get("https://ip-ranges.amazonaws.com/ip-ranges.json") + + if err != nil { + return fmt.Errorf("Error listing IP ranges: %s", err) + } + + defer res.Body.Close() + + data, err := ioutil.ReadAll(res.Body) + + if err != nil { + return fmt.Errorf("Error reading response body: %s", err) + } + + result := new(dataSourceAwsIPRangesResult) + + if err := json.Unmarshal(data, result); err != nil { + return fmt.Errorf("Error parsing result: %s", err) + } + + if err := d.Set("create_date", result.CreateDate); err != nil { + return fmt.Errorf("Error setting create date: %s", err) + } + + if err := d.Set("sync_token", result.SyncToken); err != nil { + return fmt.Errorf("Error setting sync token: %s", err) + } + + var ( + regions = d.Get("regions").(*schema.Set) + services = d.Get("services").(*schema.Set) + noRegionFilter = regions.Len() == 0 + noServiceFilter = services.Len() == 0 + prefixes []string + ) + + for _, e := range result.Prefixes { + + var ( + matchRegion = noRegionFilter || regions.Contains(strings.ToLower(e.Region)) + matchService = noServiceFilter || services.Contains(strings.ToLower(e.Service)) + ) + + if matchRegion && matchService { + prefixes = append(prefixes, e.IpPrefix) + } + + } + + if len(prefixes) == 0 { + log.Printf("[WARN] No ip ranges result from filters") + } + + sort.Strings(prefixes) + + if err := d.Set("blocks", prefixes); err != nil { + return fmt.Errorf("Error setting ip ranges: %s", err) + } + + return nil + +} diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 69e264dd92..e15931225c 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -114,6 +114,7 @@ func Provider() terraform.ResourceProvider { "aws_ami": dataSourceAwsAmi(), "aws_availability_zones": dataSourceAwsAvailabilityZones(), "aws_iam_policy_document": dataSourceAwsIamPolicyDocument(), + "aws_ip_ranges": dataSourceAwsIPRanges(), "aws_s3_bucket_object": dataSourceAwsS3BucketObject(), "aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(), },