github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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/ukcloud/govcloudair/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 }