github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/vcd/resource_vcd_firewall_rules.go (about)

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