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 }