-
Notifications
You must be signed in to change notification settings - Fork 54
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
[CC-4083] IP Allowlist Feature for Consul Cluster #455
Conversation
@@ -296,8 +296,8 @@ func Test_validateConsulClusterTier(t *testing.T) { | |||
expected: diag.Diagnostics{ | |||
diag.Diagnostic{ | |||
Severity: diag.Error, | |||
Summary: "expected dev to be one of [DEVELOPMENT STANDARD PLUS]", | |||
Detail: "expected dev to be one of [DEVELOPMENT STANDARD PLUS] (value is case-insensitive).", | |||
Summary: "expected dev to be one of [DEVELOPMENT STANDARD PLUS PREMIUM]", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updating the go SDK (hashicorp/hcp-sdk-go#164) added this field. Had to fix this test
dff3ddd
to
8bb7a16
Compare
} | ||
`) | ||
|
||
func consulClusterConfig(clusterID string, opt string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created this helper function that creates the hcp_consul_cluster
for the tests cases.
), | ||
}, | ||
// Tests update failure for IP Allowlist with too duplicate CIDRs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy to move all these tests in their own TestAccConsulCluster_IPAllowlist
function, but this is likely going to increase CI time as resources need to be created for the tests to run. If we prefer clarity, that makes sense. I was reading this contributing guide and it seemed to prefer minimal resource creation.
@@ -178,6 +178,40 @@ func validateConsulClusterSize(v interface{}, path cty.Path) diag.Diagnostics { | |||
return diagnostics | |||
} | |||
|
|||
func validateConsulClusterCIDR(v interface{}, path cty.Path) diag.Diagnostics { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the more ideal user experience would be to check for duplicates at the plan stage as well. Unless that's something only the backend can validate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this comment for discussion on this. I can't add a validateFunc for the schema type (schema.TypeList not supported) to check for duplicates on all items
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know if you prefer another existing pattern to verify on plan, as I'm new to this repo!
@@ -629,9 +673,10 @@ func resourceConsulClusterUpdate(ctx context.Context, d *schema.ResourceData, me | |||
// Confirm update fields have been changed | |||
sizeChanged := d.HasChange("size") | |||
versionChanged := d.HasChange("min_consul_version") | |||
ipAllowlistChanged := d.HasChange("ip_allowlist") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For any updates:
- Detect changes in
ip_allowlist
- if changes,
buildIPAllowlist()
to validate there are no duplicates. This will return an empty list if there are no ip_allowlist entries, and otherwise a list with consul model objects that the API - Send update request
@@ -329,6 +352,13 @@ func resourceConsulClusterCreate(ctx context.Context, d *schema.ResourceData, me | |||
// The peering happens within the secondary cluster create operation. | |||
autoHvnToHvnPeering := d.Get("auto_hvn_to_hvn_peering").(bool) | |||
|
|||
// Convert ip_allowlist to consul model. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For creates:
- Get
ip_allowlist
value
-buildIPAllowlist()
to validate there are no duplicates in the entries. This will also return an empty list if there are no ip_allowlist entries, and otherwise a list with consul model objects that the API expects. - Send create request
Updates seem to be failing with the following errors from the consul service backend.
I think the Edit: backend fix in the works, this client code remains 👍🏽 Ready to review, but I will update the test output and screenshots once fixed on the backend side. |
address := cidrMap["address"].(string) | ||
description := cidrMap["description"].(string) | ||
|
||
ip, _, _ := net.ParseCIDR(address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validation (validators.go) occurs first , so this should be valid (no error). I omitted handling it, but happy to do it if this feels like bad practice.
} | ||
|
||
// Seen holds validated CIDRs. | ||
seen := make(map[string]struct{}, len(cidrs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a hashmap to validate duplicates. See the following comment on why I went with this approach:
https://github.com/hashicorp/terraform-provider-hcp/pull/455/files#r1102997970
Alternatives discussed in that comment:
- use
schema.TypeSet
for the ip_allowlist field - don't do validation ( backend does it)
@@ -767,3 +832,37 @@ func resourceConsulClusterImport(ctx context.Context, d *schema.ResourceData, me | |||
|
|||
return []*schema.ResourceData{d}, nil | |||
} | |||
|
|||
// buildIPAllowlist validates there are no duplicate CIDRs and returns a consul model. | |||
func buildIPAllowlist(cidrs []interface{}) ([]*consulmodels.HashicorpCloudConsul20210204CidrRange, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function is only used to check for duplicates, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed duplicate logic now, but it also converts the ip_allowlist
from a terraform list (type []interface{}
) to a model that can be used by the consul client.
Used across a few operations so it's nice to have it
@@ -534,6 +565,19 @@ func setConsulClusterResourceData(d *schema.ResourceData, cluster *consulmodels. | |||
} | |||
} | |||
|
|||
var ipAllowlist []interface{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
address = "172.25.16.0/24" | ||
description = "this is an IPV4 address" | ||
} | ||
`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could it be worthwhile to include an IPV6 address in the test case objects? Or do we currently only support IPV4 addresses?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure I can do that, I believe they are allowed. I checked the original RFC for this feature, but it's not explicit. Maybe @loshz can confirm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm looks like creation fails with IPV6...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JolisaBrownHashiCorp We've confirmed that IPV6 is disallowed. I've added a validation to inform the user if they try to use one in this commit: 75ddd6a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome. @Achooo Thanks for following up! May I ask what your slack handle is? I'm getting a deletion error when attempting to run the test suite and would like to inbox you the logs to discuss.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing, it's @ashvitha
, I've sent you a DM :)
@@ -193,7 +243,11 @@ func TestAccConsulCluster(t *testing.T) { | |||
Config: testConfig(setTestAccConsulClusterConfig(updatedConsulCluster)), | |||
Check: resource.ComposeTestCheckFunc( | |||
testAccCheckConsulClusterExists(resourceName), | |||
resource.TestCheckResourceAttr(resourceName, "size", "SMALL"), | |||
resource.TestCheckResourceAttr(resourceName, "size", "MEDIUM"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to change to a STANDARD
. This update test was failing with the following error:
Error: error updating Consul cluster (test-202302131304): [PATCH /consul/2021-02-04/organizations/{cluster.location.organization_id}/projects/{cluster.location.project_id}/clusters/{cluster.id}][400] Update default &{Code:3 Details:[] Error:Development tier clusters only have one size and cannot be changed. Message:Development tier clusters only have one size and cannot be changed.}
Development clusters cannot change sizes
7688839
to
468c6f5
Compare
569011a
to
8f90e92
Compare
8f90e92
to
fde3e7b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great! Have left a few minor comments/nits.
Planning to test this locally asap and report back.
@@ -534,6 +564,19 @@ func setConsulClusterResourceData(d *schema.ResourceData, cluster *consulmodels. | |||
} | |||
} | |||
|
|||
ipAllowlist := make([]map[string]interface{}, len(cluster.Config.NetworkConfig.IPAllowlist)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need the nil NetworkConfig check here too?
|
||
// buildIPAllowlist returns a consul model for the IP allowlist. | ||
func buildIPAllowlist(cidrs []interface{}) ([]*consulmodels.HashicorpCloudConsul20210204CidrRange, error) { | ||
IPAllowList := make([]*consulmodels.HashicorpCloudConsul20210204CidrRange, len(cidrs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor nit:
IPAllowList := make([]*consulmodels.HashicorpCloudConsul20210204CidrRange, len(cidrs)) | |
ipAllowList := make([]*consulmodels.HashicorpCloudConsul20210204CidrRange, len(cidrs)) |
All of the E2E tests work for me on remote-dev. I was able to successfully create and update a cluster with an IP Allowlist, as well as load an existing cluster as a data source. |
Commit formatting suggestions Co-authored-by: Dan Bond <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solid work, Ash! 👍
🛠️ Description
ip_allowlist
to thehcp_consul_cluster
resource to support IP Allowlisting - a Block List (list of objects).🏗️ Acceptance tests
Output from acceptance testing:
End to End Tests (int)
Resource CREATE
make dev
in root of repotest/
main.tf
with following :terraform init
terraform apply
Datasource (READ ONLY)
main.tf
with the following:terraform apply
Resource UPDATE
hcp_consul_cluster
resource:terraform apply

The data source output we added in the step before now shows the updated `ip_allowlist`Validation
No more than 3 CIDRs
Description Length
Invalid CIDR