Skip to content

Commit

Permalink
IFACE-1880: Enable RFC 6598 CIDR Range for HVN Route (#515)
Browse files Browse the repository at this point in the history
* IFACE-1880 Revise validators to differentiate between HVN and HVN Route allowed CIDR ranges:
- Allow RFC 6598 (shared address space) for HVN route CIDRs

* IFACE-1880 Update HVN destination_cidr to use a specific (non-shared) validator

* IFACE-1880 Update HVN Route destination_cidr to use a specific (non-shared) validator

* IFACE-1880 Reorganize CIDR validation tests

* IFACE-1880 Add more test cases for CIDR validation for HVN Routes

* IFACE-1880 Add changelog entry

* IFACE-1880 Update docs for hvn_route resource to include note about destination_cidr

* IFACE-1880 Update doc template for hvn_route resource to include note about destination_cidr and generate docs
  • Loading branch information
jasonpilz authored May 30, 2023
1 parent e79219a commit b02a523
Show file tree
Hide file tree
Showing 7 changed files with 550 additions and 225 deletions.
3 changes: 3 additions & 0 deletions .changelog/515.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
Update HVN Route validation for `destination_cidr` attribute to allow RFC6598 CIDR range.
```
3 changes: 3 additions & 0 deletions docs/resources/hvn_route.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ description: |-
~> **Migration Required:** The release of HVN Routes in v0.7.0 includes breaking changes that affect `hcp_aws_network_peering` and `hcp_aws_transit_gateway_attachment`. [This guide](https://registry.terraform.io/providers/hashicorp/hcp/latest/docs/guides/hvn-route-migration-guide) walks through how to migrate to the new resource syntax.
Please pin to the previous version to avoid disruption until you are ready to migrate.

-> **Note:** The `destination_cidr` value must be an IPv4 CIDR block within the [RFC1918](https://datatracker.ietf.org/doc/html/rfc1918) private address space (10.*.*.*, 192.168.*.*, 172.[16-31].*.*) **or**
the [RFC6598](https://datatracker.ietf.org/doc/html/rfc6598) shared address space (100.64.*.*).

The HVN route resource allows you to manage an HVN route.

## Example Usage
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/resource_hvn.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func resourceHvn() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateDiagFunc: validateCIDRBlock,
ValidateDiagFunc: validateCIDRBlockHVN,
Computed: true,
},
"project_id": {
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/resource_hvn_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func resourceHvnRoute() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateDiagFunc: validateCIDRBlock,
ValidateDiagFunc: validateCIDRBlockHVNRoute,
},
"target_link": {
Description: "A unique URL identifying the target of the HVN route. Examples of the target: [`aws_network_peering`](aws_network_peering.md), [`aws_transit_gateway_attachment`](aws_transit_gateway_attachment.md)",
Expand Down
63 changes: 42 additions & 21 deletions internal/provider/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,36 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

var (
// RFC1918Networks are networks defined as per RFC 1918 (Private Address Space)
RFC1918Networks = []net.IPNet{
{
// 10.*.*.*
IP: net.IPv4(10, 0, 0, 0),
Mask: net.IPv4Mask(255, 0, 0, 0),
},
{
// 192.168.*.*
IP: net.IPv4(192, 168, 0, 0),
Mask: net.IPv4Mask(255, 255, 0, 0),
},
{
// 172.[16-31].*.*
IP: net.IPv4(172, 16, 0, 0),
Mask: net.IPv4Mask(255, 240, 0, 0),
},
}

// RFC6598Networks are networks defined as per RFC 6598 (Shared Address Space)
RFC6598Networks = []net.IPNet{
{
// 100.[64-127].*.* /10
IP: net.IPv4(100, 64, 0, 0),
Mask: net.IPv4Mask(255, 192, 0, 0),
},
}
)

// validateStringNotEmpty ensures a given string is non-empty.
func validateStringNotEmpty(v interface{}, path cty.Path) diag.Diagnostics {
var diagnostics diag.Diagnostics
Expand Down Expand Up @@ -310,27 +340,18 @@ func validateVaultPathsFilter(v interface{}, path cty.Path) diag.Diagnostics {
return diagnostics
}

func validateCIDRBlock(v interface{}, path cty.Path) diag.Diagnostics {
var diagnostics diag.Diagnostics
func validateCIDRBlockHVN(v interface{}, path cty.Path) diag.Diagnostics {
// HVNs allow RFC 1918 Network CIDRs
return validateCIDRBlock(v, path, RFC1918Networks)
}

// validRanges contains the set of IP ranges considered valid.
var validRanges = []net.IPNet{
{
// 10.*.*.*
IP: net.IPv4(10, 0, 0, 0),
Mask: net.IPv4Mask(255, 0, 0, 0),
},
{
// 192.168.*.*
IP: net.IPv4(192, 168, 0, 0),
Mask: net.IPv4Mask(255, 255, 0, 0),
},
{
// 172.[16-31].*.*
IP: net.IPv4(172, 16, 0, 0),
Mask: net.IPv4Mask(255, 240, 0, 0),
},
}
func validateCIDRBlockHVNRoute(v interface{}, path cty.Path) diag.Diagnostics {
// HVN Routes allow RFC 1918 and RFC 6598 Network CIDRs
return validateCIDRBlock(v, path, append(RFC1918Networks, RFC6598Networks...))
}

func validateCIDRBlock(v interface{}, path cty.Path, networks []net.IPNet) diag.Diagnostics {
var diagnostics diag.Diagnostics

// parse the string as CIDR notation IP address and prefix length.
ip, net, err := net.ParseCIDR(v.(string))
Expand All @@ -348,7 +369,7 @@ func validateCIDRBlock(v interface{}, path cty.Path) diag.Diagnostics {

// validate if the IP address is contained in one of the expected ranges.
valid := false
for _, validRange := range validRanges {
for _, validRange := range networks {
valueSize, _ := net.Mask.Size()
validRangeSize, _ := validRange.Mask.Size()
if validRange.Contains(ip) && valueSize >= validRangeSize {
Expand Down
Loading

0 comments on commit b02a523

Please sign in to comment.