2017-06-12 16:30:22 +02:00
|
|
|
package openstack
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
|
|
|
|
"github.com/gophercloud/gophercloud"
|
|
|
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
|
|
|
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
|
|
)
|
|
|
|
|
|
|
|
func resourceFWRuleV1() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceFWRuleV1Create,
|
|
|
|
Read: resourceFWRuleV1Read,
|
|
|
|
Update: resourceFWRuleV1Update,
|
|
|
|
Delete: resourceFWRuleV1Delete,
|
|
|
|
Importer: &schema.ResourceImporter{
|
|
|
|
State: schema.ImportStatePassthrough,
|
|
|
|
},
|
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"region": &schema.Schema{
|
2017-06-16 22:31:31 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
ForceNew: true,
|
2017-06-12 16:30:22 +02:00
|
|
|
},
|
|
|
|
"name": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"description": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"protocol": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"action": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"ip_version": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Default: 4,
|
|
|
|
},
|
|
|
|
"source_ip_address": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"destination_ip_address": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"source_port": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"destination_port": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"enabled": &schema.Schema{
|
|
|
|
Type: schema.TypeBool,
|
|
|
|
Optional: true,
|
|
|
|
Default: true,
|
|
|
|
},
|
|
|
|
"tenant_id": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"value_specs": &schema.Schema{
|
|
|
|
Type: schema.TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceFWRuleV1Create(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
|
|
|
|
config := meta.(*Config)
|
2017-06-16 22:31:31 +02:00
|
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d, config))
|
2017-06-12 16:30:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
enabled := d.Get("enabled").(bool)
|
|
|
|
ipVersion := resourceFWRuleV1DetermineIPVersion(d.Get("ip_version").(int))
|
|
|
|
protocol := resourceFWRuleV1DetermineProtocol(d.Get("protocol").(string))
|
|
|
|
|
|
|
|
ruleConfiguration := RuleCreateOpts{
|
|
|
|
rules.CreateOpts{
|
|
|
|
Name: d.Get("name").(string),
|
|
|
|
Description: d.Get("description").(string),
|
|
|
|
Protocol: protocol,
|
|
|
|
Action: d.Get("action").(string),
|
|
|
|
IPVersion: ipVersion,
|
|
|
|
SourceIPAddress: d.Get("source_ip_address").(string),
|
|
|
|
DestinationIPAddress: d.Get("destination_ip_address").(string),
|
|
|
|
SourcePort: d.Get("source_port").(string),
|
|
|
|
DestinationPort: d.Get("destination_port").(string),
|
|
|
|
Enabled: &enabled,
|
|
|
|
TenantID: d.Get("tenant_id").(string),
|
|
|
|
},
|
|
|
|
MapValueSpecs(d),
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Create firewall rule: %#v", ruleConfiguration)
|
|
|
|
|
|
|
|
rule, err := rules.Create(networkingClient, ruleConfiguration).Extract()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Firewall rule with id %s : %#v", rule.ID, rule)
|
|
|
|
|
|
|
|
d.SetId(rule.ID)
|
|
|
|
|
|
|
|
return resourceFWRuleV1Read(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceFWRuleV1Read(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
log.Printf("[DEBUG] Retrieve information about firewall rule: %s", d.Id())
|
|
|
|
|
|
|
|
config := meta.(*Config)
|
2017-06-16 22:31:31 +02:00
|
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d, config))
|
2017-06-12 16:30:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
rule, err := rules.Get(networkingClient, d.Id()).Extract()
|
|
|
|
if err != nil {
|
|
|
|
return CheckDeleted(d, err, "FW rule")
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Read OpenStack Firewall Rule %s: %#v", d.Id(), rule)
|
|
|
|
|
|
|
|
d.Set("action", rule.Action)
|
|
|
|
d.Set("name", rule.Name)
|
|
|
|
d.Set("description", rule.Description)
|
|
|
|
d.Set("ip_version", rule.IPVersion)
|
|
|
|
d.Set("source_ip_address", rule.SourceIPAddress)
|
|
|
|
d.Set("destination_ip_address", rule.DestinationIPAddress)
|
|
|
|
d.Set("source_port", rule.SourcePort)
|
|
|
|
d.Set("destination_port", rule.DestinationPort)
|
|
|
|
d.Set("enabled", rule.Enabled)
|
|
|
|
|
|
|
|
if rule.Protocol == "" {
|
|
|
|
d.Set("protocol", "any")
|
|
|
|
} else {
|
|
|
|
d.Set("protocol", rule.Protocol)
|
|
|
|
}
|
|
|
|
|
2017-06-16 22:31:31 +02:00
|
|
|
d.Set("region", GetRegion(d, config))
|
2017-06-12 16:30:22 +02:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceFWRuleV1Update(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
config := meta.(*Config)
|
2017-06-16 22:31:31 +02:00
|
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d, config))
|
2017-06-12 16:30:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
opts := rules.UpdateOpts{}
|
|
|
|
|
|
|
|
if d.HasChange("name") {
|
|
|
|
v := d.Get("name").(string)
|
|
|
|
opts.Name = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("description") {
|
|
|
|
v := d.Get("description").(string)
|
|
|
|
opts.Description = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("protocol") {
|
|
|
|
v := d.Get("protocol").(string)
|
|
|
|
opts.Protocol = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("action") {
|
|
|
|
v := d.Get("action").(string)
|
|
|
|
opts.Action = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("ip_version") {
|
|
|
|
v := d.Get("ip_version").(int)
|
|
|
|
ipVersion := resourceFWRuleV1DetermineIPVersion(v)
|
|
|
|
opts.IPVersion = &ipVersion
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("source_ip_address") {
|
|
|
|
v := d.Get("source_ip_address").(string)
|
|
|
|
opts.SourceIPAddress = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("destination_ip_address") {
|
|
|
|
v := d.Get("destination_ip_address").(string)
|
|
|
|
opts.DestinationIPAddress = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("source_port") {
|
|
|
|
v := d.Get("source_port").(string)
|
|
|
|
opts.SourcePort = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("destination_port") {
|
|
|
|
v := d.Get("destination_port").(string)
|
|
|
|
opts.DestinationPort = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.HasChange("enabled") {
|
|
|
|
v := d.Get("enabled").(bool)
|
|
|
|
opts.Enabled = &v
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Updating firewall rules: %#v", opts)
|
|
|
|
|
|
|
|
err = rules.Update(networkingClient, d.Id(), opts).Err
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return resourceFWRuleV1Read(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceFWRuleV1Delete(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
log.Printf("[DEBUG] Destroy firewall rule: %s", d.Id())
|
|
|
|
|
|
|
|
config := meta.(*Config)
|
2017-06-16 22:31:31 +02:00
|
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d, config))
|
2017-06-12 16:30:22 +02:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
rule, err := rules.Get(networkingClient, d.Id()).Extract()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if rule.PolicyID != "" {
|
|
|
|
_, err := policies.RemoveRule(networkingClient, rule.PolicyID, rule.ID).Extract()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rules.Delete(networkingClient, d.Id()).Err
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceFWRuleV1DetermineIPVersion(ipv int) gophercloud.IPVersion {
|
|
|
|
// Determine the IP Version
|
|
|
|
var ipVersion gophercloud.IPVersion
|
|
|
|
switch ipv {
|
|
|
|
case 4:
|
|
|
|
ipVersion = gophercloud.IPv4
|
|
|
|
case 6:
|
|
|
|
ipVersion = gophercloud.IPv6
|
|
|
|
}
|
|
|
|
|
|
|
|
return ipVersion
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceFWRuleV1DetermineProtocol(p string) rules.Protocol {
|
|
|
|
var protocol rules.Protocol
|
|
|
|
switch p {
|
|
|
|
case "any":
|
|
|
|
protocol = rules.ProtocolAny
|
|
|
|
case "icmp":
|
|
|
|
protocol = rules.ProtocolICMP
|
|
|
|
case "tcp":
|
|
|
|
protocol = rules.ProtocolTCP
|
|
|
|
case "udp":
|
|
|
|
protocol = rules.ProtocolUDP
|
|
|
|
}
|
|
|
|
|
|
|
|
return protocol
|
|
|
|
}
|