github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/resource_aws_waf_rule.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/aws/aws-sdk-go/aws"
     8  	"github.com/aws/aws-sdk-go/aws/awserr"
     9  	"github.com/aws/aws-sdk-go/service/waf"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  )
    12  
    13  func resourceAwsWafRule() *schema.Resource {
    14  	return &schema.Resource{
    15  		Create: resourceAwsWafRuleCreate,
    16  		Read:   resourceAwsWafRuleRead,
    17  		Update: resourceAwsWafRuleUpdate,
    18  		Delete: resourceAwsWafRuleDelete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"name": &schema.Schema{
    22  				Type:     schema.TypeString,
    23  				Required: true,
    24  				ForceNew: true,
    25  			},
    26  			"metric_name": &schema.Schema{
    27  				Type:     schema.TypeString,
    28  				Required: true,
    29  				ForceNew: true,
    30  			},
    31  			"predicates": &schema.Schema{
    32  				Type:     schema.TypeSet,
    33  				Optional: true,
    34  				Elem: &schema.Resource{
    35  					Schema: map[string]*schema.Schema{
    36  						"negated": &schema.Schema{
    37  							Type:     schema.TypeBool,
    38  							Required: true,
    39  						},
    40  						"data_id": &schema.Schema{
    41  							Type:     schema.TypeString,
    42  							Optional: true,
    43  							ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    44  								value := v.(string)
    45  								if len(value) > 128 {
    46  									errors = append(errors, fmt.Errorf(
    47  										"%q cannot be longer than 128 characters", k))
    48  								}
    49  								return
    50  							},
    51  						},
    52  						"type": &schema.Schema{
    53  							Type:     schema.TypeString,
    54  							Required: true,
    55  							ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    56  								value := v.(string)
    57  								if value != "IPMatch" && value != "ByteMatch" && value != "SqlInjectionMatch" && value != "SizeConstraint" && value != "XssMatch" {
    58  									errors = append(errors, fmt.Errorf(
    59  										"%q must be one of IPMatch | ByteMatch | SqlInjectionMatch | SizeConstraint | XssMatch", k))
    60  								}
    61  								return
    62  							},
    63  						},
    64  					},
    65  				},
    66  			},
    67  		},
    68  	}
    69  }
    70  
    71  func resourceAwsWafRuleCreate(d *schema.ResourceData, meta interface{}) error {
    72  	conn := meta.(*AWSClient).wafconn
    73  
    74  	// ChangeToken
    75  	var ct *waf.GetChangeTokenInput
    76  
    77  	res, err := conn.GetChangeToken(ct)
    78  	if err != nil {
    79  		return fmt.Errorf("Error getting change token: %s", err)
    80  	}
    81  
    82  	params := &waf.CreateRuleInput{
    83  		ChangeToken: res.ChangeToken,
    84  		MetricName:  aws.String(d.Get("metric_name").(string)),
    85  		Name:        aws.String(d.Get("name").(string)),
    86  	}
    87  
    88  	resp, err := conn.CreateRule(params)
    89  	if err != nil {
    90  		return err
    91  	}
    92  	d.SetId(*resp.Rule.RuleId)
    93  	return resourceAwsWafRuleUpdate(d, meta)
    94  }
    95  
    96  func resourceAwsWafRuleRead(d *schema.ResourceData, meta interface{}) error {
    97  	conn := meta.(*AWSClient).wafconn
    98  
    99  	params := &waf.GetRuleInput{
   100  		RuleId: aws.String(d.Id()),
   101  	}
   102  
   103  	resp, err := conn.GetRule(params)
   104  	if err != nil {
   105  		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "WAFNonexistentItemException" {
   106  			log.Printf("[WARN] WAF Rule (%s) not found, error code (404)", d.Id())
   107  			d.SetId("")
   108  			return nil
   109  		}
   110  
   111  		return err
   112  	}
   113  
   114  	var predicates []map[string]interface{}
   115  
   116  	for _, predicateSet := range resp.Rule.Predicates {
   117  		predicate := map[string]interface{}{
   118  			"negated": *predicateSet.Negated,
   119  			"type":    *predicateSet.Type,
   120  			"data_id": *predicateSet.DataId,
   121  		}
   122  		predicates = append(predicates, predicate)
   123  	}
   124  
   125  	d.Set("predicates", predicates)
   126  	d.Set("name", resp.Rule.Name)
   127  	d.Set("metric_name", resp.Rule.MetricName)
   128  
   129  	return nil
   130  }
   131  
   132  func resourceAwsWafRuleUpdate(d *schema.ResourceData, meta interface{}) error {
   133  	err := updateWafRuleResource(d, meta, waf.ChangeActionInsert)
   134  	if err != nil {
   135  		return fmt.Errorf("Error Updating WAF Rule: %s", err)
   136  	}
   137  	return resourceAwsWafRuleRead(d, meta)
   138  }
   139  
   140  func resourceAwsWafRuleDelete(d *schema.ResourceData, meta interface{}) error {
   141  	conn := meta.(*AWSClient).wafconn
   142  	err := updateWafRuleResource(d, meta, waf.ChangeActionDelete)
   143  	if err != nil {
   144  		return fmt.Errorf("Error Removing WAF Rule Predicates: %s", err)
   145  	}
   146  	// ChangeToken
   147  	var ct *waf.GetChangeTokenInput
   148  
   149  	resp, err := conn.GetChangeToken(ct)
   150  
   151  	req := &waf.DeleteRuleInput{
   152  		ChangeToken: resp.ChangeToken,
   153  		RuleId:      aws.String(d.Id()),
   154  	}
   155  	log.Printf("[INFO] Deleting WAF Rule")
   156  	_, err = conn.DeleteRule(req)
   157  
   158  	if err != nil {
   159  		return fmt.Errorf("Error deleting WAF Rule: %s", err)
   160  	}
   161  
   162  	return nil
   163  }
   164  
   165  func updateWafRuleResource(d *schema.ResourceData, meta interface{}, ChangeAction string) error {
   166  	conn := meta.(*AWSClient).wafconn
   167  
   168  	// ChangeToken
   169  	var ct *waf.GetChangeTokenInput
   170  
   171  	resp, err := conn.GetChangeToken(ct)
   172  	if err != nil {
   173  		return fmt.Errorf("Error getting change token: %s", err)
   174  	}
   175  
   176  	req := &waf.UpdateRuleInput{
   177  		ChangeToken: resp.ChangeToken,
   178  		RuleId:      aws.String(d.Id()),
   179  	}
   180  
   181  	predicatesSet := d.Get("predicates").(*schema.Set)
   182  	for _, predicateI := range predicatesSet.List() {
   183  		predicate := predicateI.(map[string]interface{})
   184  		updatePredicate := &waf.RuleUpdate{
   185  			Action: aws.String(ChangeAction),
   186  			Predicate: &waf.Predicate{
   187  				Negated: aws.Bool(predicate["negated"].(bool)),
   188  				Type:    aws.String(predicate["type"].(string)),
   189  				DataId:  aws.String(predicate["data_id"].(string)),
   190  			},
   191  		}
   192  		req.Updates = append(req.Updates, updatePredicate)
   193  	}
   194  
   195  	_, err = conn.UpdateRule(req)
   196  	if err != nil {
   197  		return fmt.Errorf("Error Updating WAF Rule: %s", err)
   198  	}
   199  
   200  	return nil
   201  }