github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/resource_aws_waf_web_acl.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 resourceAwsWafWebAcl() *schema.Resource {
    14  	return &schema.Resource{
    15  		Create: resourceAwsWafWebAclCreate,
    16  		Read:   resourceAwsWafWebAclRead,
    17  		Update: resourceAwsWafWebAclUpdate,
    18  		Delete: resourceAwsWafWebAclDelete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"name": &schema.Schema{
    22  				Type:     schema.TypeString,
    23  				Required: true,
    24  				ForceNew: true,
    25  			},
    26  			"default_action": &schema.Schema{
    27  				Type:     schema.TypeSet,
    28  				Required: true,
    29  				MaxItems: 1,
    30  				Elem: &schema.Resource{
    31  					Schema: map[string]*schema.Schema{
    32  						"type": &schema.Schema{
    33  							Type:     schema.TypeString,
    34  							Required: true,
    35  						},
    36  					},
    37  				},
    38  			},
    39  			"metric_name": &schema.Schema{
    40  				Type:     schema.TypeString,
    41  				Required: true,
    42  				ForceNew: true,
    43  			},
    44  			"rules": &schema.Schema{
    45  				Type:     schema.TypeSet,
    46  				Optional: true,
    47  				Elem: &schema.Resource{
    48  					Schema: map[string]*schema.Schema{
    49  						"action": &schema.Schema{
    50  							Type:     schema.TypeSet,
    51  							Required: true,
    52  							MaxItems: 1,
    53  							Elem: &schema.Resource{
    54  								Schema: map[string]*schema.Schema{
    55  									"type": &schema.Schema{
    56  										Type:     schema.TypeString,
    57  										Required: true,
    58  									},
    59  								},
    60  							},
    61  						},
    62  						"priority": &schema.Schema{
    63  							Type:     schema.TypeInt,
    64  							Required: true,
    65  						},
    66  						"rule_id": &schema.Schema{
    67  							Type:     schema.TypeString,
    68  							Required: true,
    69  						},
    70  					},
    71  				},
    72  			},
    73  		},
    74  	}
    75  }
    76  
    77  func resourceAwsWafWebAclCreate(d *schema.ResourceData, meta interface{}) error {
    78  	conn := meta.(*AWSClient).wafconn
    79  
    80  	// ChangeToken
    81  	var ct *waf.GetChangeTokenInput
    82  
    83  	res, err := conn.GetChangeToken(ct)
    84  	if err != nil {
    85  		return fmt.Errorf("Error getting change token: %s", err)
    86  	}
    87  
    88  	params := &waf.CreateWebACLInput{
    89  		ChangeToken:   res.ChangeToken,
    90  		DefaultAction: expandDefaultAction(d),
    91  		MetricName:    aws.String(d.Get("metric_name").(string)),
    92  		Name:          aws.String(d.Get("name").(string)),
    93  	}
    94  
    95  	resp, err := conn.CreateWebACL(params)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	d.SetId(*resp.WebACL.WebACLId)
   100  	return resourceAwsWafWebAclUpdate(d, meta)
   101  }
   102  
   103  func resourceAwsWafWebAclRead(d *schema.ResourceData, meta interface{}) error {
   104  	conn := meta.(*AWSClient).wafconn
   105  	params := &waf.GetWebACLInput{
   106  		WebACLId: aws.String(d.Id()),
   107  	}
   108  
   109  	resp, err := conn.GetWebACL(params)
   110  	if err != nil {
   111  		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "WAFNonexistentItemException" {
   112  			log.Printf("[WARN] WAF ACL (%s) not found, error code (404)", d.Id())
   113  			d.SetId("")
   114  			return nil
   115  		}
   116  
   117  		return err
   118  	}
   119  
   120  	defaultAction := flattenDefaultAction(resp.WebACL.DefaultAction)
   121  	if defaultAction != nil {
   122  		if err := d.Set("default_action", defaultAction); err != nil {
   123  			return fmt.Errorf("error setting default_action: %s", err)
   124  		}
   125  	}
   126  	d.Set("name", resp.WebACL.Name)
   127  	d.Set("metric_name", resp.WebACL.MetricName)
   128  
   129  	return nil
   130  }
   131  
   132  func resourceAwsWafWebAclUpdate(d *schema.ResourceData, meta interface{}) error {
   133  	err := updateWebAclResource(d, meta, waf.ChangeActionInsert)
   134  	if err != nil {
   135  		return fmt.Errorf("Error Updating WAF ACL: %s", err)
   136  	}
   137  	return resourceAwsWafWebAclRead(d, meta)
   138  }
   139  
   140  func resourceAwsWafWebAclDelete(d *schema.ResourceData, meta interface{}) error {
   141  	conn := meta.(*AWSClient).wafconn
   142  	err := updateWebAclResource(d, meta, waf.ChangeActionDelete)
   143  	if err != nil {
   144  		return fmt.Errorf("Error Removing WAF ACL Rules: %s", err)
   145  	}
   146  
   147  	var ct *waf.GetChangeTokenInput
   148  
   149  	resp, err := conn.GetChangeToken(ct)
   150  
   151  	req := &waf.DeleteWebACLInput{
   152  		ChangeToken: resp.ChangeToken,
   153  		WebACLId:    aws.String(d.Id()),
   154  	}
   155  
   156  	log.Printf("[INFO] Deleting WAF ACL")
   157  	_, err = conn.DeleteWebACL(req)
   158  
   159  	if err != nil {
   160  		return fmt.Errorf("Error Deleting WAF ACL: %s", err)
   161  	}
   162  	return nil
   163  }
   164  
   165  func updateWebAclResource(d *schema.ResourceData, meta interface{}, ChangeAction string) error {
   166  	conn := meta.(*AWSClient).wafconn
   167  	// ChangeToken
   168  	var ct *waf.GetChangeTokenInput
   169  
   170  	resp, err := conn.GetChangeToken(ct)
   171  	if err != nil {
   172  		return fmt.Errorf("Error getting change token: %s", err)
   173  	}
   174  
   175  	req := &waf.UpdateWebACLInput{
   176  		ChangeToken: resp.ChangeToken,
   177  		WebACLId:    aws.String(d.Id()),
   178  	}
   179  
   180  	if d.HasChange("default_action") {
   181  		req.DefaultAction = expandDefaultAction(d)
   182  	}
   183  
   184  	rules := d.Get("rules").(*schema.Set)
   185  	for _, rule := range rules.List() {
   186  		aclRule := rule.(map[string]interface{})
   187  		action := aclRule["action"].(*schema.Set).List()[0].(map[string]interface{})
   188  		aclRuleUpdate := &waf.WebACLUpdate{
   189  			Action: aws.String(ChangeAction),
   190  			ActivatedRule: &waf.ActivatedRule{
   191  				Priority: aws.Int64(int64(aclRule["priority"].(int))),
   192  				RuleId:   aws.String(aclRule["rule_id"].(string)),
   193  				Action:   &waf.WafAction{Type: aws.String(action["type"].(string))},
   194  			},
   195  		}
   196  		req.Updates = append(req.Updates, aclRuleUpdate)
   197  	}
   198  	_, err = conn.UpdateWebACL(req)
   199  	if err != nil {
   200  		return fmt.Errorf("Error Updating WAF ACL: %s", err)
   201  	}
   202  	return nil
   203  }
   204  
   205  func expandDefaultAction(d *schema.ResourceData) *waf.WafAction {
   206  	set, ok := d.GetOk("default_action")
   207  	if !ok {
   208  		return nil
   209  	}
   210  
   211  	s := set.(*schema.Set).List()
   212  	if s == nil || len(s) == 0 {
   213  		return nil
   214  	}
   215  
   216  	if s[0] == nil {
   217  		log.Printf("[ERR] First element of Default Action is set to nil")
   218  		return nil
   219  	}
   220  
   221  	dA := s[0].(map[string]interface{})
   222  
   223  	return &waf.WafAction{
   224  		Type: aws.String(dA["type"].(string)),
   225  	}
   226  }
   227  
   228  func flattenDefaultAction(n *waf.WafAction) []map[string]interface{} {
   229  	if n == nil {
   230  		return nil
   231  	}
   232  
   233  	m := setMap(make(map[string]interface{}))
   234  
   235  	m.SetString("type", n.Type)
   236  	return m.MapList()
   237  }