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