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