Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Case-insensitive comparison of IPv6 addresses #468

Merged
merged 1 commit into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/hetznercloud/terraform-provider-hcloud
require (
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.1
github.com/hetznercloud/hcloud-go v1.31.1
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
Expand Down Expand Up @@ -255,8 +254,8 @@ github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv
github.com/hashicorp/terraform-plugin-go v0.3.0/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM=
github.com/hashicorp/terraform-plugin-go v0.3.1 h1:ML+THFcqpdR049gqrbEFDFo99va2Wqw9g4XDPy51euU=
github.com/hashicorp/terraform-plugin-go v0.3.1/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 h1:SuI59MqNjYDrL7EfqHX9V6P/24isgqYx/FdglwVs9bg=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0/go.mod h1:grseeRo9g3yNkYW09iFlV8LG78jTa1ssBgouogQg/RU=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.1 h1:vpzKKP2dIFb9n89AG8Wxl758/5JSZWZH0OuKdlq0M38=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.1/go.mod h1:o3pdss6ynDZW9FfiZ+rETUH5LEVufrXdhwLU+5OiRo0=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20210707203944-259a57b3608c h1:nqkErwUGfpZZMqj29WZ9U/wz2OpJVDuiokLhE/3Y7IQ=
Expand Down Expand Up @@ -340,7 +339,6 @@ github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
64 changes: 64 additions & 0 deletions internal/e2etests/firewall/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,70 @@ func TestFirewallResource_ApplyTo(t *testing.T) {
})
}

func TestFirewallResource_SourceIPs_IPv6Comparison(t *testing.T) {
var f hcloud.Firewall

res := firewall.NewRData(t, "ipv6-firewall", []firewall.RDataRule{
{
Direction: "in",
Protocol: "tcp",
SourceIPs: []string{"Aaaa:aaaa:aaaa:aaaa::/64"},
Port: "22",
},
}, nil)
tmplMan := testtemplate.Manager{}

resource.Test(t, resource.TestCase{
PreCheck: e2etests.PreCheck(t),
Providers: e2etests.Providers(),
CheckDestroy: testsupport.CheckResourcesDestroyed(firewall.ResourceType, firewall.ByID(t, &f)),
Steps: []resource.TestStep{
{
Config: tmplMan.Render(t, "testdata/r/hcloud_firewall", res),
Check: resource.ComposeTestCheckFunc(
testsupport.CheckResourceExists(res.TFID(), firewall.ByID(t, &f)),
),
},
{
Config: tmplMan.Render(t, "testdata/r/hcloud_firewall", res),
PlanOnly: true,
},
},
})
}

func TestFirewallResource_DestinationIPs_IPv6Comparison(t *testing.T) {
var f hcloud.Firewall

res := firewall.NewRData(t, "ipv6-firewall", []firewall.RDataRule{
{
Direction: "out",
Protocol: "tcp",
DestinationIPs: []string{"Aaaa:aaaa:aaaa:aaaa::/64"},
Port: "22",
},
}, nil)
tmplMan := testtemplate.Manager{}

resource.Test(t, resource.TestCase{
PreCheck: e2etests.PreCheck(t),
Providers: e2etests.Providers(),
CheckDestroy: testsupport.CheckResourcesDestroyed(firewall.ResourceType, firewall.ByID(t, &f)),
Steps: []resource.TestStep{
{
Config: tmplMan.Render(t, "testdata/r/hcloud_firewall", res),
Check: resource.ComposeTestCheckFunc(
testsupport.CheckResourceExists(res.TFID(), firewall.ByID(t, &f)),
),
},
{
Config: tmplMan.Render(t, "testdata/r/hcloud_firewall", res),
PlanOnly: true,
},
},
})
}

func hasFirewallRule(
t *testing.T,
f *hcloud.Firewall,
Expand Down
42 changes: 32 additions & 10 deletions internal/firewall/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"
"net"
"strconv"
"strings"

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
Expand Down Expand Up @@ -77,7 +78,6 @@ func Resource() *schema.Resource {
switch hcloud.FirewallRuleDirection(direction) {
case hcloud.FirewallRuleDirectionIn:
case hcloud.FirewallRuleDirectionOut:
return nil
default:
return diag.Errorf("%s is not a valid direction", direction)
}
Expand All @@ -95,7 +95,6 @@ func Resource() *schema.Resource {
case hcloud.FirewallRuleProtocolUDP:
case hcloud.FirewallRuleProtocolESP:
case hcloud.FirewallRuleProtocolGRE:
return nil
default:
return diag.Errorf("%s is not a valid protocol", protocol)
}
Expand All @@ -111,6 +110,9 @@ func Resource() *schema.Resource {
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: validateIPDiag,
StateFunc: func(i interface{}) string {
return strings.ToLower(i.(string))
},
},
Optional: true,
},
Expand All @@ -119,6 +121,9 @@ func Resource() *schema.Resource {
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: validateIPDiag,
StateFunc: func(i interface{}) string {
return strings.ToLower(i.(string))
},
},
Optional: true,
},
Expand All @@ -141,8 +146,9 @@ func resourceFirewallCreate(ctx context.Context, d *schema.ResourceData, m inter
}
if rules, ok := d.GetOk("rule"); ok {
for _, tfRawRule := range rules.(*schema.Set).List() {
rule := toHcloudRule(tfRawRule)
opts.Rules = append(opts.Rules, rule)
if rule, ok := toHcloudRule(tfRawRule); ok {
opts.Rules = append(opts.Rules, rule)
}
}
}
if labels, ok := d.GetOk("labels"); ok {
Expand Down Expand Up @@ -176,11 +182,26 @@ func resourceFirewallCreate(ctx context.Context, d *schema.ResourceData, m inter
return resourceFirewallRead(ctx, d, m)
}

func toHcloudRule(tfRawRule interface{}) hcloud.FirewallRule {
func toHcloudRule(tfRawRule interface{}) (hcloud.FirewallRule, bool) {
tfRule := tfRawRule.(map[string]interface{})
direction := tfRule["direction"].(string)
protocol := tfRule["protocol"].(string)

if direction == "" || protocol == "" {
// We need to use state funcs in the schema above in order to normalize
// the values for source and destination IPs. However, this triggers
// Terraform SDK bug #160
// (https://github.com/hashicorp/terraform-plugin-sdk/issues/160):
// we get a defunct entry in the rules set. Since we always require
// protocol and direction to be set, we can just check if they are
// empty. In this case we can ignore the entry when talking to our API
// (https://github.com/hashicorp/terraform-plugin-sdk/issues/160#issuecomment-522935697).
return hcloud.FirewallRule{}, false
}

rule := hcloud.FirewallRule{
Direction: hcloud.FirewallRuleDirection(tfRule["direction"].(string)),
Protocol: hcloud.FirewallRuleProtocol(tfRule["protocol"].(string)),
Direction: hcloud.FirewallRuleDirection(direction),
Protocol: hcloud.FirewallRuleProtocol(protocol),
}
rawPort := tfRule["port"].(string)
if rawPort != "" {
Expand All @@ -200,7 +221,7 @@ func toHcloudRule(tfRawRule interface{}) hcloud.FirewallRule {
_, destination, _ := net.ParseCIDR(destinationIP.(string))
rule.DestinationIPs = append(rule.DestinationIPs, *destination)
}
return rule
return rule, true
}

func toTFRule(hcloudRule hcloud.FirewallRule) map[string]interface{} {
Expand Down Expand Up @@ -287,8 +308,9 @@ func resourceFirewallUpdate(ctx context.Context, d *schema.ResourceData, m inter
if tfRules, ok := d.GetOk("rule"); ok {
var rules []hcloud.FirewallRule
for _, tfRawRule := range tfRules.(*schema.Set).List() {
rule := toHcloudRule(tfRawRule)
rules = append(rules, rule)
if rule, ok := toHcloudRule(tfRawRule); ok {
rules = append(rules, rule)
}
}
actions, _, err := client.Firewall.SetRules(ctx, firewall, hcloud.FirewallSetRulesOpts{Rules: rules})
if err != nil {
Expand Down