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

Subnet nacl association #18807

Merged
merged 73 commits into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
49408fa
created resource files. Copied test file from another resource
geofflancaster Feb 17, 2021
88f90a2
working test case
geofflancaster Apr 12, 2021
382b6cb
removed unused code
geofflancaster Apr 12, 2021
5a682ab
updated read function
geofflancaster Apr 12, 2021
1017b06
reformated markdown
geofflancaster Apr 12, 2021
fa6df7b
fixed lint errors
geofflancaster Apr 12, 2021
98181a5
fixed md lint error
geofflancaster Apr 12, 2021
e0d21a4
lint updates
geofflancaster Apr 13, 2021
c6cb16c
lint error fixes
geofflancaster Apr 13, 2021
daa5fc5
update markdown
geofflancaster Apr 13, 2021
456a2f9
fixed fmt
geofflancaster Apr 13, 2021
7a6816a
fixed missing subnet association error
geofflancaster Apr 14, 2021
98dc232
added lint ignore
geofflancaster Apr 14, 2021
5b84987
trying to get the nilerr lint to pass
geofflancaster Apr 14, 2021
894f358
switch from lint:ignore to nolint
geofflancaster Apr 14, 2021
f08c8da
removed update code since it isn't used
geofflancaster Apr 14, 2021
3a50f44
Merge remote-tracking branch 'origin' into subnet-nacl-association
geofflancaster Oct 20, 2021
9d0cbb0
updated per refactor
geofflancaster Oct 25, 2021
f732cee
updated per refactor
geofflancaster Oct 25, 2021
b35ae0a
Merge branch 'subnet-nacl-association' of github.com:geofflancaster/t…
geofflancaster Oct 25, 2021
3d0f350
Merge branch 'main' into subnet-nacl-association
geofflancaster Oct 25, 2021
d3650c6
updated package name
geofflancaster Oct 25, 2021
8717215
Merge branch 'subnet-nacl-association' of github.com:geofflancaster/t…
geofflancaster Oct 25, 2021
6e8fe29
fixed most missing dependencies
geofflancaster Oct 25, 2021
b7fccd1
refactor
geofflancaster Oct 25, 2021
d06b2cb
refactor 2
geofflancaster Oct 25, 2021
9bfc3e1
removed test init
geofflancaster Oct 25, 2021
c2f1ba7
updated test
geofflancaster Oct 25, 2021
292a36d
removed nolint comments
geofflancaster Oct 25, 2021
7f23ede
fixing lint errors
geofflancaster Oct 25, 2021
0abb17b
trying to fix lint error
geofflancaster Oct 25, 2021
0ef5b02
linting
geofflancaster Oct 25, 2021
c8f0b22
lint
geofflancaster Oct 26, 2021
10d1291
Merge branch 'main' into HEAD
ewbankkit Feb 3, 2022
0ddc84a
r/aws_network_acl_association: Tweak function names.
ewbankkit Feb 3, 2022
64c0324
Additional TODO.
ewbankkit Feb 3, 2022
00dd498
r/aws_network_acl_association: Tidy up.
ewbankkit Feb 3, 2022
69144aa
Merge branch 'main' into tmp-pr18807
ewbankkit Feb 4, 2022
0c0127c
r/aws_network_acl_association: Start improvement of acceptance tests.
ewbankkit Feb 4, 2022
57ab970
r/aws_network_acl_association: Add 'TestAccEC2NetworkACLAssociation_d…
ewbankkit Feb 4, 2022
a634db2
r/aws_network_acl_association: Add 'TestAccEC2NetworkACLAssociation_t…
ewbankkit Feb 4, 2022
0599960
r/aws_network_acl: Alphabetize attributes.
ewbankkit Feb 4, 2022
711e7d2
r/aws_network_acl: Start to tidy up resource Create and Delete.
ewbankkit Feb 4, 2022
3c10b43
'Network ACL Association' -> 'EC2 Network ACL Association'.
ewbankkit Feb 4, 2022
df6e264
r/aws_network_acl: Tidy up resource Read.
ewbankkit Feb 4, 2022
99574d2
Add 'networkACLAssociationCreate'.
ewbankkit Feb 4, 2022
f44b718
Revert "Add 'networkACLAssociationCreate'."
ewbankkit Feb 4, 2022
4bdc652
Revert "Revert "Add 'networkACLAssociationCreate'.""
ewbankkit Feb 4, 2022
e135839
r/aws_network_acl: Tidy up resource Create.
ewbankkit Feb 4, 2022
2c1df98
r/aws_network_acl: Tidy up resource Update.
ewbankkit Feb 4, 2022
3e48a1b
r/aws_network_acl: Retry creation of new NACL/Subnet association.
ewbankkit Feb 4, 2022
d8a5649
r/aws_network_acl: Add 'testAccNetworkACLConfig'.
ewbankkit Feb 5, 2022
9ff42c7
r/aws_network_acl_association: Add 'networkACLAssociationDelete'.
ewbankkit Feb 5, 2022
676548a
r/aws_network_acl: Use 'networkACLAssociationCreate'.
ewbankkit Feb 5, 2022
310e66a
r/aws_network_acl: Delete NACL associations before attempting NACL de…
ewbankkit Feb 6, 2022
228177d
r/aws_network_acl: Tidy up sweeper.
ewbankkit Feb 6, 2022
c329fcb
r/aws_network_acl_association: Add 'TestAccEC2NetworkACLAssociation_d…
ewbankkit Feb 7, 2022
93ac311
r/aws_network_acl: Prevent import of a default NACL.
ewbankkit Feb 7, 2022
4ce03d9
r/aws_network_acl: Tidy up acceptance tests.
ewbankkit Feb 7, 2022
dc9c0d4
r/aws_network_acl: Validate 'protocol'.
ewbankkit Feb 7, 2022
b27edef
r/aws_network_acl: Add 'modifyNetworkACLAttributesOnCreate' and 'dele…
ewbankkit Feb 7, 2022
0b6ab2e
Tweak 'networkACLProtocolNumber'.
ewbankkit Feb 7, 2022
6308f6a
r/aws_default_network_acl: All current acceptance tests passing.
ewbankkit Feb 7, 2022
7fe0b77
r/aws_default_network_acl: Tidy up acceptance tests.
ewbankkit Feb 7, 2022
0bd6c95
Add CHANGELOG entry.
ewbankkit Feb 7, 2022
a5fc988
r/aws_network_acl_rule: Tidy up.
ewbankkit Feb 7, 2022
987e576
r/aws_network_acl_rule: Tidy up acceptance tests.
ewbankkit Feb 8, 2022
3e0c6d7
r/aws_vpc: Restore resourceVPCCustomizeDiff functionality from #6721 …
ewbankkit Feb 8, 2022
67115bc
r/aws_network_acl_rule: All acceptance tests passing.
ewbankkit Feb 8, 2022
d093e3f
r/aws_network_acl_rule: Replace 'protocolNumbers()' etc.
ewbankkit Feb 8, 2022
7a038cf
r/aws_network_acl_association: Add 'TestAccEC2NetworkACLAssociation_a…
ewbankkit Feb 8, 2022
f372d7d
Correct documentation page file name.
ewbankkit Feb 8, 2022
f2aee7c
Fix terrafmt errors.
ewbankkit Feb 8, 2022
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
3 changes: 3 additions & 0 deletions .changelog/18807.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_network_acl_association
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,7 @@ func Provider() *schema.Provider {
"aws_main_route_table_association": ec2.ResourceMainRouteTableAssociation(),
"aws_nat_gateway": ec2.ResourceNATGateway(),
"aws_network_acl": ec2.ResourceNetworkACL(),
"aws_network_acl_association": ec2.ResourceNetworkACLAssociation(),
"aws_network_acl_rule": ec2.ResourceNetworkACLRule(),
"aws_network_interface": ec2.ResourceNetworkInterface(),
"aws_network_interface_attachment": ec2.ResourceNetworkInterfaceAttachment(),
Expand Down
298 changes: 61 additions & 237 deletions internal/service/ec2/default_network_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import (
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
Expand All @@ -23,33 +21,51 @@ const (
)

func ResourceDefaultNetworkACL() *schema.Resource {
networkACLRuleSetSchema := &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: networkACLRuleResource,
Set: networkACLRuleHash,
}

return &schema.Resource{
Create: resourceDefaultNetworkACLCreate,
// We reuse aws_network_acl's read method, the operations are the same
Read: resourceNetworkACLRead,
Delete: resourceDefaultNetworkACLDelete,
Update: resourceDefaultNetworkACLUpdate,
Delete: resourceDefaultNetworkACLDelete,

Importer: &schema.ResourceImporter{
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
d.Set("default_network_acl_id", d.Id())

return []*schema.ResourceData{d}, nil
},
},

// Keep in sync with aws_network_acl's schema with the following changes:
// - egress and ingress are not Computed and don't have "Attributes as Blocks" processing mode set
// - subnet_ids is not Computed
// and additions:
// - default_network_acl_id Required/ForceNew
Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"vpc_id": {
Type: schema.TypeString,
Computed: true,
},
"default_network_acl_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
// We want explicit management of Rules here, so we do not allow them to be
// computed. Instead, an empty config will enforce just that; removal of the
// rules
"egress": networkACLRuleSetSchema,
"ingress": networkACLRuleSetSchema,
"owner_id": {
Type: schema.TypeString,
Computed: true,
},
// We want explicit management of Subnets here, so we do not allow them to be
// computed. Instead, an empty config will enforce just that; removal of the
// any Subnets that have been assigned to the Default Network ACL. Because we
Expand All @@ -61,122 +77,9 @@ func ResourceDefaultNetworkACL() *schema.Resource {
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
// We want explicit management of Rules here, so we do not allow them to be
// computed. Instead, an empty config will enforce just that; removal of the
// rules
"ingress": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"from_port": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IsPortNumberOrZero,
},
"to_port": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IsPortNumberOrZero,
},
"rule_no": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(1, 32766),
},
"action": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
ec2.RuleActionAllow,
ec2.RuleActionDeny,
}, true),
},
"protocol": {
Type: schema.TypeString,
Required: true,
},
"cidr_block": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsCIDR,
},
"ipv6_cidr_block": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsCIDR,
},
"icmp_type": {
Type: schema.TypeInt,
Optional: true,
},
"icmp_code": {
Type: schema.TypeInt,
Optional: true,
},
},
},
Set: resourceNetworkACLEntryHash,
},
"egress": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"from_port": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IsPortNumberOrZero,
},
"to_port": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IsPortNumberOrZero,
},
"rule_no": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validation.IntBetween(1, 32766),
},
"action": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
ec2.RuleActionAllow,
ec2.RuleActionDeny,
}, true),
},
"protocol": {
Type: schema.TypeString,
Required: true,
},
"cidr_block": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsCIDR,
},
"ipv6_cidr_block": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsCIDR,
},
"icmp_type": {
Type: schema.TypeInt,
Optional: true,
},
"icmp_code": {
Type: schema.TypeInt,
Optional: true,
},
},
},
Set: resourceNetworkACLEntryHash,
},

"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),

"owner_id": {
"vpc_id": {
Type: schema.TypeString,
Computed: true,
},
Expand All @@ -187,144 +90,65 @@ func ResourceDefaultNetworkACL() *schema.Resource {
}

func resourceDefaultNetworkACLCreate(d *schema.ResourceData, meta interface{}) error {
d.SetId(d.Get("default_network_acl_id").(string))

// revoke all default and pre-existing rules on the default network acl.
// In the UPDATE method, we'll apply only the rules in the configuration.
log.Printf("[DEBUG] Revoking default ingress and egress rules for Default Network ACL for %s", d.Id())
err := revokeAllNetworkACLEntries(d.Id(), meta)
if err != nil {
return err
}

return resourceDefaultNetworkACLUpdate(d, meta)
}

func resourceDefaultNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).EC2Conn

if d.HasChange("ingress") {
err := updateNetworkAclEntries(d, "ingress", conn)
if err != nil {
return err
}
}
naclID := d.Get("default_network_acl_id").(string)
nacl, err := FindNetworkACLByID(conn, naclID)

if d.HasChange("egress") {
err := updateNetworkAclEntries(d, "egress", conn)
if err != nil {
return err
}
if err != nil {
return fmt.Errorf("error reading EC2 Network ACL (%s): %w", d.Id(), err)
}

if d.HasChange("subnet_ids") {
o, n := d.GetChange("subnet_ids")
if o == nil {
o = new(schema.Set)
}
if n == nil {
n = new(schema.Set)
}

os := o.(*schema.Set)
ns := n.(*schema.Set)
if !aws.BoolValue(nacl.IsDefault) {
return fmt.Errorf("use the `aws_network_acl` resource instead")
}

remove := os.Difference(ns).List()
add := ns.Difference(os).List()
d.SetId(naclID)

if len(remove) > 0 {
//
// NO-OP
//
// Subnets *must* belong to a Network ACL. Subnets are not "removed" from
// Network ACLs, instead their association is replaced. In a normal
// Network ACL, any removal of a Subnet is done by replacing the
// Subnet/ACL association with an association between the Subnet and the
// Default Network ACL. Because we're managing the default here, we cannot
// do that, so we simply log a NO-OP. In order to remove the Subnet here,
// it must be destroyed, or assigned to different Network ACL. Those
// operations are not handled here
log.Printf("[WARN] Cannot remove subnets from the Default Network ACL. They must be re-assigned or destroyed")
}
// Revoke all default and pre-existing rules on the default network ACL.
if err := deleteNetworkAclEntries(conn, d.Id(), nacl.Entries); err != nil {
return err
}

if len(add) > 0 {
for _, a := range add {
association, err := findNetworkAclAssociation(a.(string), conn)
if err != nil {
return fmt.Errorf("Failed to find acl association: acl %s with subnet %s: %s", d.Id(), a, err)
}
log.Printf("[DEBUG] Updating Network Association for Default Network ACL (%s) and Subnet (%s)", d.Id(), a.(string))
_, err = conn.ReplaceNetworkAclAssociation(&ec2.ReplaceNetworkAclAssociationInput{
AssociationId: association.NetworkAclAssociationId,
NetworkAclId: aws.String(d.Id()),
})
if err != nil {
return err
}
}
}
if err := modifyNetworkACLAttributesOnCreate(conn, d); err != nil {
return err
}

if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")
// Configure tags.
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig
newTags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))).IgnoreConfig(ignoreTagsConfig)
oldTags := KeyValueTags(nacl.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

if err := UpdateTags(conn, d.Id(), o, n); err != nil {
return fmt.Errorf("error updating EC2 Default Network ACL (%s) tags: %s", d.Id(), err)
if !oldTags.Equal(newTags) {
if err := UpdateTags(conn, d.Id(), oldTags, newTags); err != nil {
return fmt.Errorf("error updating EC2 Default Network ACL (%s) tags: %w", d.Id(), err)
}
}

// Re-use the exiting Network ACL Resources READ method
return resourceNetworkACLRead(d, meta)
}

func resourceDefaultNetworkACLDelete(d *schema.ResourceData, meta interface{}) error {
log.Printf("[WARN] Cannot destroy Default Network ACL. Terraform will remove this resource from the state file, however resources may remain.")
return nil
}

// revokeAllNetworkACLEntries revoke all ingress and egress rules that the Default
// Network ACL currently has
func revokeAllNetworkACLEntries(netaclId string, meta interface{}) error {
func resourceDefaultNetworkACLUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).EC2Conn

resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{
NetworkAclIds: []*string{aws.String(netaclId)},
})

if err != nil {
log.Printf("[DEBUG] Error looking up Network ACL: %s", err)
// Subnets *must* belong to a Network ACL. Subnets are not "removed" from
// Network ACLs, instead their association is replaced. In a normal
// Network ACL, any removal of a Subnet is done by replacing the
// Subnet/ACL association with an association between the Subnet and the
// Default Network ACL. Because we're managing the default here, we cannot
// do that, so we simply log a NO-OP. In order to remove the Subnet here,
// it must be destroyed, or assigned to different Network ACL. Those
// operations are not handled here.
if err := modifyNetworkACLAttributesOnUpdate(conn, d, false); err != nil {
return err
}

if resp == nil {
return fmt.Errorf("Error looking up Default Network ACL Entries: No results")
}

networkAcl := resp.NetworkAcls[0]
for _, e := range networkAcl.Entries {
// Skip the default rules added by AWS. They can be neither
// configured or deleted by users. See http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_ACLs.html#default-network-acl
if aws.Int64Value(e.RuleNumber) == defaultACLRuleNumberIPv4 ||
aws.Int64Value(e.RuleNumber) == defaultACLRuleNumberIPv6 {
continue
}

// track if this is an egress or ingress rule, for logging purposes
rt := "ingress"
if aws.BoolValue(e.Egress) {
rt = "egress"
}
return resourceNetworkACLRead(d, meta)
}

log.Printf("[DEBUG] Destroying Network ACL (%s) Entry number (%d)", rt, int(*e.RuleNumber))
_, err := conn.DeleteNetworkAclEntry(&ec2.DeleteNetworkAclEntryInput{
NetworkAclId: aws.String(netaclId),
RuleNumber: e.RuleNumber,
Egress: e.Egress,
})
if err != nil {
return fmt.Errorf("Error deleting entry (%s): %s", e, err)
}
}
func resourceDefaultNetworkACLDelete(d *schema.ResourceData, meta interface{}) error {
log.Printf("[WARN] EC2 Default Network ACL (%s) not deleted, removing from state", d.Id())

return nil
}
Loading