github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/builtin/providers/vcd/resource_vcd_firewall_rules.go (about)

     1  package vcd
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/terraform/helper/schema"
     9  	types "github.com/hmrc/vmware-govcd/types/v56"
    10  )
    11  
    12  func resourceVcdFirewallRules() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceVcdFirewallRulesCreate,
    15  		Delete: resourceFirewallRulesDelete,
    16  		Read:   resourceFirewallRulesRead,
    17  
    18  		Schema: map[string]*schema.Schema{
    19  			"edge_gateway": &schema.Schema{
    20  				Type:     schema.TypeString,
    21  				Required: true,
    22  				ForceNew: true,
    23  			},
    24  
    25  			"default_action": &schema.Schema{
    26  				Type:     schema.TypeString,
    27  				Required: true,
    28  				ForceNew: true,
    29  			},
    30  
    31  			"rule": &schema.Schema{
    32  				Type:     schema.TypeList,
    33  				Optional: true,
    34  				ForceNew: true,
    35  				Elem: &schema.Resource{
    36  					Schema: map[string]*schema.Schema{
    37  						"id": &schema.Schema{
    38  							Type:     schema.TypeString,
    39  							Optional: true,
    40  							Computed: true,
    41  						},
    42  
    43  						"description": &schema.Schema{
    44  							Type:     schema.TypeString,
    45  							Required: true,
    46  						},
    47  
    48  						"policy": &schema.Schema{
    49  							Type:     schema.TypeString,
    50  							Required: true,
    51  						},
    52  
    53  						"protocol": &schema.Schema{
    54  							Type:     schema.TypeString,
    55  							Required: true,
    56  						},
    57  
    58  						"destination_port": &schema.Schema{
    59  							Type:     schema.TypeString,
    60  							Required: true,
    61  						},
    62  
    63  						"destination_ip": &schema.Schema{
    64  							Type:     schema.TypeString,
    65  							Required: true,
    66  						},
    67  
    68  						"source_port": &schema.Schema{
    69  							Type:     schema.TypeString,
    70  							Required: true,
    71  						},
    72  
    73  						"source_ip": &schema.Schema{
    74  							Type:     schema.TypeString,
    75  							Required: true,
    76  						},
    77  					},
    78  				},
    79  			},
    80  		},
    81  	}
    82  }
    83  
    84  func resourceVcdFirewallRulesCreate(d *schema.ResourceData, meta interface{}) error {
    85  	vcdClient := meta.(*VCDClient)
    86  	vcdClient.Mutex.Lock()
    87  	defer vcdClient.Mutex.Unlock()
    88  
    89  	edgeGateway, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
    90  	if err != nil {
    91  		return fmt.Errorf("Unable to find edge gateway: %s", err)
    92  	}
    93  
    94  	err = retryCall(vcdClient.MaxRetryTimeout, func() error {
    95  		edgeGateway.Refresh()
    96  		firewallRules, _ := expandFirewallRules(d, edgeGateway.EdgeGateway)
    97  		task, err := edgeGateway.CreateFirewallRules(d.Get("default_action").(string), firewallRules)
    98  		if err != nil {
    99  			log.Printf("[INFO] Error setting firewall rules: %s", err)
   100  			return fmt.Errorf("Error setting firewall rules: %#v", err)
   101  		}
   102  
   103  		return task.WaitTaskCompletion()
   104  	})
   105  	if err != nil {
   106  		return fmt.Errorf("Error completing tasks: %#v", err)
   107  	}
   108  
   109  	d.SetId(d.Get("edge_gateway").(string))
   110  
   111  	return resourceFirewallRulesRead(d, meta)
   112  }
   113  
   114  func resourceFirewallRulesDelete(d *schema.ResourceData, meta interface{}) error {
   115  	vcdClient := meta.(*VCDClient)
   116  	vcdClient.Mutex.Lock()
   117  	defer vcdClient.Mutex.Unlock()
   118  
   119  	edgeGateway, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
   120  
   121  	firewallRules := deleteFirewallRules(d, edgeGateway.EdgeGateway)
   122  	defaultAction := edgeGateway.EdgeGateway.Configuration.EdgeGatewayServiceConfiguration.FirewallService.DefaultAction
   123  	task, err := edgeGateway.CreateFirewallRules(defaultAction, firewallRules)
   124  	if err != nil {
   125  		return fmt.Errorf("Error deleting firewall rules: %#v", err)
   126  	}
   127  
   128  	err = task.WaitTaskCompletion()
   129  	if err != nil {
   130  		return fmt.Errorf("Error completing tasks: %#v", err)
   131  	}
   132  
   133  	return nil
   134  }
   135  
   136  func resourceFirewallRulesRead(d *schema.ResourceData, meta interface{}) error {
   137  	vcdClient := meta.(*VCDClient)
   138  
   139  	edgeGateway, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
   140  	if err != nil {
   141  		return fmt.Errorf("Error finding edge gateway: %#v", err)
   142  	}
   143  	ruleList := d.Get("rule").([]interface{})
   144  	firewallRules := *edgeGateway.EdgeGateway.Configuration.EdgeGatewayServiceConfiguration.FirewallService
   145  	rulesCount := d.Get("rule.#").(int)
   146  	for i := 0; i < rulesCount; i++ {
   147  		prefix := fmt.Sprintf("rule.%d", i)
   148  		if d.Get(prefix+".id").(string) == "" {
   149  			log.Printf("[INFO] Rule %d has no id. Searching...", i)
   150  			ruleid, err := matchFirewallRule(d, prefix, firewallRules.FirewallRule)
   151  			if err == nil {
   152  				currentRule := ruleList[i].(map[string]interface{})
   153  				currentRule["id"] = ruleid
   154  				ruleList[i] = currentRule
   155  			}
   156  		}
   157  	}
   158  	d.Set("rule", ruleList)
   159  	d.Set("default_action", firewallRules.DefaultAction)
   160  
   161  	return nil
   162  }
   163  
   164  func deleteFirewallRules(d *schema.ResourceData, gateway *types.EdgeGateway) []*types.FirewallRule {
   165  	firewallRules := gateway.Configuration.EdgeGatewayServiceConfiguration.FirewallService.FirewallRule
   166  	rulesCount := d.Get("rule.#").(int)
   167  	fwrules := make([]*types.FirewallRule, 0, len(firewallRules)-rulesCount)
   168  
   169  	for _, f := range firewallRules {
   170  		keep := true
   171  		for i := 0; i < rulesCount; i++ {
   172  			if d.Get(fmt.Sprintf("rule.%d.id", i)).(string) != f.ID {
   173  				continue
   174  			}
   175  			keep = false
   176  		}
   177  		if keep {
   178  			fwrules = append(fwrules, f)
   179  		}
   180  	}
   181  	return fwrules
   182  }
   183  
   184  func matchFirewallRule(d *schema.ResourceData, prefix string, rules []*types.FirewallRule) (string, error) {
   185  
   186  	for _, m := range rules {
   187  		if d.Get(prefix+".description").(string) == m.Description &&
   188  			d.Get(prefix+".policy").(string) == m.Policy &&
   189  			strings.ToLower(d.Get(prefix+".protocol").(string)) == getProtocol(*m.Protocols) &&
   190  			strings.ToLower(d.Get(prefix+".destination_port").(string)) == getPortString(m.Port) &&
   191  			strings.ToLower(d.Get(prefix+".destination_ip").(string)) == strings.ToLower(m.DestinationIP) &&
   192  			strings.ToLower(d.Get(prefix+".source_port").(string)) == getPortString(m.SourcePort) &&
   193  			strings.ToLower(d.Get(prefix+".source_ip").(string)) == strings.ToLower(m.SourceIP) {
   194  			return m.ID, nil
   195  		}
   196  	}
   197  	return "", fmt.Errorf("Unable to find rule")
   198  }