diff --git a/examples/ibm-is-vpc/main.tf b/examples/ibm-is-vpc/main.tf index e5c240286e..c8881507d1 100644 --- a/examples/ibm-is-vpc/main.tf +++ b/examples/ibm-is-vpc/main.tf @@ -340,6 +340,11 @@ resource "ibm_is_network_acl" "isExampleACL" { } } +resource "ibm_is_subnet_network_acl_attachment" attach { + subnet = ibm_is_subnet.subnet1.id + network_acl = ibm_is_network_acl.isExampleACL.id +} + resource "ibm_is_public_gateway" "publicgateway1" { name = "gateway1" vpc = ibm_is_vpc.vpc1.id diff --git a/ibm/provider.go b/ibm/provider.go index f150f71d8f..058045f83f 100644 --- a/ibm/provider.go +++ b/ibm/provider.go @@ -387,6 +387,7 @@ func Provider() terraform.ResourceProvider { "ibm_is_security_group_rule": resourceIBMISSecurityGroupRule(), "ibm_is_security_group_network_interface_attachment": resourceIBMISSecurityGroupNetworkInterfaceAttachment(), "ibm_is_subnet": resourceIBMISSubnet(), + "ibm_is_subnet_network_acl_attachment": resourceIBMISSubnetNetworkACLAttachment(), "ibm_is_ssh_key": resourceIBMISSSHKey(), "ibm_is_volume": resourceIBMISVolume(), "ibm_is_vpn_gateway": resourceIBMISVPNGateway(), diff --git a/ibm/resource_ibm_is_subnet_network_acl_attachment.go b/ibm/resource_ibm_is_subnet_network_acl_attachment.go new file mode 100644 index 0000000000..28d801ec30 --- /dev/null +++ b/ibm/resource_ibm_is_subnet_network_acl_attachment.go @@ -0,0 +1,435 @@ +package ibm + +import ( + "fmt" + "log" + "reflect" + "time" + + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +const ( + isSubnetID = "subnet" + isNetworkACLID = "network_acl" +) + +func resourceIBMISSubnetNetworkACLAttachment() *schema.Resource { + return &schema.Resource{ + Create: resourceIBMISSubnetNetworkACLAttachmentCreate, + Read: resourceIBMISSubnetNetworkACLAttachmentRead, + Update: resourceIBMISSubnetNetworkACLAttachmentUpdate, + Delete: resourceIBMISSubnetNetworkACLAttachmentDelete, + Exists: resourceIBMISSubnetNetworkACLAttachmentExists, + Importer: &schema.ResourceImporter{}, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + Update: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + + isSubnetID: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The subnet identifier", + }, + + isNetworkACLID: { + Type: schema.TypeString, + Required: true, + Description: "The unique identifier of network ACL", + }, + + isNetworkACLName: { + Type: schema.TypeString, + Computed: true, + Description: "Network ACL name", + }, + + isNetworkACLVPC: { + Type: schema.TypeString, + Computed: true, + Description: "Network ACL VPC", + }, + + isNetworkACLResourceGroup: { + Type: schema.TypeString, + Computed: true, + Description: "Resource group ID for the network ACL", + }, + + isNetworkACLRules: { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + isNetworkACLRuleID: { + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this Network ACL rule", + }, + isNetworkACLRuleName: { + Type: schema.TypeString, + Computed: true, + Description: "The user-defined name for this rule", + }, + isNetworkACLRuleAction: { + Type: schema.TypeString, + Computed: true, + Description: "Whether to allow or deny matching traffic", + }, + isNetworkACLRuleIPVersion: { + Type: schema.TypeString, + Computed: true, + Description: "The IP version for this rule", + }, + isNetworkACLRuleSource: { + Type: schema.TypeString, + Computed: true, + Description: "The source CIDR block", + }, + isNetworkACLRuleDestination: { + Type: schema.TypeString, + Computed: true, + Description: "The destination CIDR block", + }, + isNetworkACLRuleDirection: { + Type: schema.TypeString, + Computed: true, + Description: "Direction of traffic to enforce, either inbound or outbound", + }, + isNetworkACLRuleICMP: { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + isNetworkACLRuleICMPCode: { + Type: schema.TypeInt, + Computed: true, + Description: "The ICMP traffic code to allow", + }, + isNetworkACLRuleICMPType: { + Type: schema.TypeInt, + Computed: true, + Description: "The ICMP traffic type to allow", + }, + }, + }, + }, + + isNetworkACLRuleTCP: { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + isNetworkACLRulePortMax: { + Type: schema.TypeInt, + Computed: true, + Description: "The inclusive upper bound of TCP destination port range", + }, + isNetworkACLRulePortMin: { + Type: schema.TypeInt, + Computed: true, + Description: "The inclusive lower bound of TCP destination port range", + }, + isNetworkACLRuleSourcePortMax: { + Type: schema.TypeInt, + Computed: true, + Description: "The inclusive upper bound of TCP source port range", + }, + isNetworkACLRuleSourcePortMin: { + Type: schema.TypeInt, + Computed: true, + Description: "The inclusive lower bound of TCP source port range", + }, + }, + }, + }, + + isNetworkACLRuleUDP: { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + isNetworkACLRulePortMax: { + Type: schema.TypeInt, + Computed: true, + Description: "The inclusive upper bound of UDP destination port range", + }, + isNetworkACLRulePortMin: { + Type: schema.TypeInt, + Computed: true, + Description: "The inclusive lower bound of UDP destination port range", + }, + isNetworkACLRuleSourcePortMax: { + Type: schema.TypeInt, + Computed: true, + Description: "The inclusive upper bound of UDP source port range", + }, + isNetworkACLRuleSourcePortMin: { + Type: schema.TypeInt, + Computed: true, + Description: "The inclusive lower bound of UDP source port range", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func resourceIBMISSubnetNetworkACLAttachmentCreate(d *schema.ResourceData, meta interface{}) error { + sess, err := vpcClient(meta) + if err != nil { + return err + } + + subnet := d.Get(isSubnetID).(string) + networkACL := d.Get(isNetworkACLID).(string) + + // Construct an instance of the NetworkACLIdentityByID model + networkACLIdentityModel := new(vpcv1.NetworkACLIdentityByID) + networkACLIdentityModel.ID = &networkACL + + // Construct an instance of the ReplaceSubnetNetworkACLOptions model + replaceSubnetNetworkACLOptionsModel := new(vpcv1.ReplaceSubnetNetworkACLOptions) + replaceSubnetNetworkACLOptionsModel.ID = &subnet + replaceSubnetNetworkACLOptionsModel.NetworkACLIdentity = networkACLIdentityModel + resultACL, response, err := sess.ReplaceSubnetNetworkACL(replaceSubnetNetworkACLOptionsModel) + + if err != nil { + log.Printf("[DEBUG] Error while attaching a network ACL to a subnet %s\n%s", err, response) + return fmt.Errorf("Error while attaching a network ACL to a subnet %s\n%s", err, response) + } + d.SetId(subnet) + log.Printf("[INFO] Network ACL : %s", *resultACL.ID) + log.Printf("[INFO] Subnet ID : %s", subnet) + + return resourceIBMISSubnetNetworkACLAttachmentRead(d, meta) +} + +func resourceIBMISSubnetNetworkACLAttachmentRead(d *schema.ResourceData, meta interface{}) error { + id := d.Id() + sess, err := vpcClient(meta) + if err != nil { + return err + } + + getSubnetNetworkACLOptionsModel := &vpcv1.GetSubnetNetworkACLOptions{ + ID: &id, + } + nwacl, response, err := sess.GetSubnetNetworkACL(getSubnetNetworkACLOptionsModel) + + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + return fmt.Errorf("Error getting subnet's (%s) attached network ACL: %s\n%s", id, err, response) + } + d.Set(isNetworkACLName, *nwacl.Name) + d.Set(isNetworkACLVPC, *nwacl.VPC.ID) + if nwacl.ResourceGroup != nil { + d.Set(isNetworkACLResourceGroup, *nwacl.ResourceGroup.ID) + } + + rules := make([]interface{}, 0) + if len(nwacl.Rules) > 0 { + for _, rulex := range nwacl.Rules { + log.Println("[DEBUG] Type of the Rule", reflect.TypeOf(rulex)) + rule := make(map[string]interface{}) + switch reflect.TypeOf(rulex).String() { + case "*vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolIcmp": + { + rulex := rulex.(*vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolIcmp) + rule[isNetworkACLRuleID] = *rulex.ID + rule[isNetworkACLRuleName] = *rulex.Name + rule[isNetworkACLRuleAction] = *rulex.Action + rule[isNetworkACLRuleIPVersion] = *rulex.IPVersion + rule[isNetworkACLRuleSource] = *rulex.Source + rule[isNetworkACLRuleDestination] = *rulex.Destination + rule[isNetworkACLRuleDirection] = *rulex.Direction + rule[isNetworkACLRuleTCP] = make([]map[string]int, 0, 0) + rule[isNetworkACLRuleUDP] = make([]map[string]int, 0, 0) + icmp := make([]map[string]int, 1, 1) + if rulex.Code != nil && rulex.Type != nil { + icmp[0] = map[string]int{ + isNetworkACLRuleICMPCode: int(*rulex.Code), + isNetworkACLRuleICMPType: int(*rulex.Code), + } + } + rule[isNetworkACLRuleICMP] = icmp + } + case "*vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolTcpudp": + { + rulex := rulex.(*vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolTcpudp) + rule[isNetworkACLRuleID] = *rulex.ID + rule[isNetworkACLRuleName] = *rulex.Name + rule[isNetworkACLRuleAction] = *rulex.Action + rule[isNetworkACLRuleIPVersion] = *rulex.IPVersion + rule[isNetworkACLRuleSource] = *rulex.Source + rule[isNetworkACLRuleDestination] = *rulex.Destination + rule[isNetworkACLRuleDirection] = *rulex.Direction + if *rulex.Protocol == "tcp" { + rule[isNetworkACLRuleICMP] = make([]map[string]int, 0, 0) + rule[isNetworkACLRuleUDP] = make([]map[string]int, 0, 0) + tcp := make([]map[string]int, 1, 1) + tcp[0] = map[string]int{ + isNetworkACLRuleSourcePortMax: checkNetworkACLNil(rulex.SourcePortMax), + isNetworkACLRuleSourcePortMin: checkNetworkACLNil(rulex.SourcePortMin), + } + tcp[0][isNetworkACLRulePortMax] = checkNetworkACLNil(rulex.DestinationPortMax) + tcp[0][isNetworkACLRulePortMin] = checkNetworkACLNil(rulex.DestinationPortMin) + rule[isNetworkACLRuleTCP] = tcp + } else if *rulex.Protocol == "udp" { + rule[isNetworkACLRuleICMP] = make([]map[string]int, 0, 0) + rule[isNetworkACLRuleTCP] = make([]map[string]int, 0, 0) + udp := make([]map[string]int, 1, 1) + udp[0] = map[string]int{ + isNetworkACLRuleSourcePortMax: checkNetworkACLNil(rulex.SourcePortMax), + isNetworkACLRuleSourcePortMin: checkNetworkACLNil(rulex.SourcePortMin), + } + udp[0][isNetworkACLRulePortMax] = checkNetworkACLNil(rulex.DestinationPortMax) + udp[0][isNetworkACLRulePortMin] = checkNetworkACLNil(rulex.DestinationPortMin) + rule[isNetworkACLRuleUDP] = udp + } + } + case "*vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolAll": + { + rulex := rulex.(*vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolAll) + rule[isNetworkACLRuleID] = *rulex.ID + rule[isNetworkACLRuleName] = *rulex.Name + rule[isNetworkACLRuleAction] = *rulex.Action + rule[isNetworkACLRuleIPVersion] = *rulex.IPVersion + rule[isNetworkACLRuleSource] = *rulex.Source + rule[isNetworkACLRuleDestination] = *rulex.Destination + rule[isNetworkACLRuleDirection] = *rulex.Direction + rule[isNetworkACLRuleICMP] = make([]map[string]int, 0, 0) + rule[isNetworkACLRuleTCP] = make([]map[string]int, 0, 0) + rule[isNetworkACLRuleUDP] = make([]map[string]int, 0, 0) + } + } + rules = append(rules, rule) + } + } + d.Set(isNetworkACLRules, rules) + return nil +} + +func resourceIBMISSubnetNetworkACLAttachmentUpdate(d *schema.ResourceData, meta interface{}) error { + + sess, err := vpcClient(meta) + if err != nil { + return err + } + if d.HasChange(isNetworkACLID) { + subnet := d.Get(isSubnetID).(string) + networkACL := d.Get(isNetworkACLID).(string) + + // Construct an instance of the NetworkACLIdentityByID model + networkACLIdentityModel := new(vpcv1.NetworkACLIdentityByID) + networkACLIdentityModel.ID = &networkACL + + // Construct an instance of the ReplaceSubnetNetworkACLOptions model + replaceSubnetNetworkACLOptionsModel := new(vpcv1.ReplaceSubnetNetworkACLOptions) + replaceSubnetNetworkACLOptionsModel.ID = &subnet + replaceSubnetNetworkACLOptionsModel.NetworkACLIdentity = networkACLIdentityModel + resultACL, response, err := sess.ReplaceSubnetNetworkACL(replaceSubnetNetworkACLOptionsModel) + + if err != nil { + log.Printf("[DEBUG] Error while attaching a network ACL to a subnet %s\n%s", err, response) + return fmt.Errorf("Error while attaching a network ACL to a subnet %s\n%s", err, response) + } + log.Printf("[INFO] Updated subnet %s with Network ACL : %s", subnet, *resultACL.ID) + + d.SetId(subnet) + return resourceIBMISSubnetNetworkACLAttachmentRead(d, meta) + } + + return resourceIBMISSubnetNetworkACLAttachmentRead(d, meta) +} + +func resourceIBMISSubnetNetworkACLAttachmentDelete(d *schema.ResourceData, meta interface{}) error { + id := d.Id() + sess, err := vpcClient(meta) + if err != nil { + return err + } + // Set the subnet with VPC default network ACL + getSubnetOptions := &vpcv1.GetSubnetOptions{ + ID: &id, + } + subnet, response, err := sess.GetSubnet(getSubnetOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + return fmt.Errorf("Error Getting Subnet (%s): %s\n%s", id, err, response) + } + // Fetch VPC + vpcID := *subnet.VPC.ID + + getvpcOptions := &vpcv1.GetVPCOptions{ + ID: &vpcID, + } + vpc, response, err := sess.GetVPC(getvpcOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + return fmt.Errorf("Error getting VPC : %s\n%s", err, response) + } + + // Fetch default network ACL + if vpc.DefaultNetworkACL != nil { + log.Printf("[DEBUG] vpc default network acl is not null :%s", *vpc.DefaultNetworkACL.ID) + // Construct an instance of the NetworkACLIdentityByID model + networkACLIdentityModel := new(vpcv1.NetworkACLIdentityByID) + networkACLIdentityModel.ID = vpc.DefaultNetworkACL.ID + + // Construct an instance of the ReplaceSubnetNetworkACLOptions model + replaceSubnetNetworkACLOptionsModel := new(vpcv1.ReplaceSubnetNetworkACLOptions) + replaceSubnetNetworkACLOptionsModel.ID = &id + replaceSubnetNetworkACLOptionsModel.NetworkACLIdentity = networkACLIdentityModel + resultACL, response, err := sess.ReplaceSubnetNetworkACL(replaceSubnetNetworkACLOptionsModel) + + if err != nil { + log.Printf("[DEBUG] Error while attaching a network ACL to a subnet %s\n%s", err, response) + return fmt.Errorf("Error while attaching a network ACL to a subnet %s\n%s", err, response) + } + log.Printf("[INFO] Updated subnet %s with VPC default Network ACL : %s", id, *resultACL.ID) + } else { + log.Printf("[DEBUG] vpc default network acl is null") + } + + d.SetId("") + return nil +} + +func resourceIBMISSubnetNetworkACLAttachmentExists(d *schema.ResourceData, meta interface{}) (bool, error) { + id := d.Id() + sess, err := vpcClient(meta) + if err != nil { + return false, err + } + getSubnetNetworkACLOptionsModel := &vpcv1.GetSubnetNetworkACLOptions{ + ID: &id, + } + _, response, err := sess.GetSubnetNetworkACL(getSubnetNetworkACLOptionsModel) + if err != nil { + if response != nil && response.StatusCode == 404 { + return false, nil + } + return false, fmt.Errorf("Error getting subnet's attached network ACL: %s\n%s", err, response) + } + return true, nil +} diff --git a/ibm/resource_ibm_is_subnet_network_acl_attachment_test.go b/ibm/resource_ibm_is_subnet_network_acl_attachment_test.go new file mode 100644 index 0000000000..c86e98ff26 --- /dev/null +++ b/ibm/resource_ibm_is_subnet_network_acl_attachment_test.go @@ -0,0 +1,134 @@ +package ibm + +import ( + "errors" + "fmt" + "testing" + + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccIBMISSubnetNetworkACLAttachment_basic(t *testing.T) { + var subnetNwACL string + nwaclname := fmt.Sprintf("tfnw-acl-%d", acctest.RandIntRange(10, 100)) + vpcname := fmt.Sprintf("tfsubnet-vpc-%d", acctest.RandIntRange(10, 100)) + name1 := fmt.Sprintf("tfsubnet-%d", acctest.RandIntRange(10, 100)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: checkSubnetNetworkACLAttachmentDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMISSubnetNetworkACLAttachmentConfig(nwaclname, vpcname, name1, ISZoneName, ISCIDR), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISSubnetNetworkACLAttachmentExists("ibm_is_subnet_network_acl_attachment.attach", subnetNwACL), + ), + }, + }, + }) +} + +func checkSubnetNetworkACLAttachmentDestroy(s *terraform.State) error { + + sess, _ := testAccProvider.Meta().(ClientSession).VpcV1API() + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_is_subnet_network_acl_attachment" { + continue + } + + getSubnetNetworkACLOptionsModel := &vpcv1.GetSubnetNetworkACLOptions{ + ID: &rs.Primary.ID, + } + _, _, err := sess.GetSubnetNetworkACL(getSubnetNetworkACLOptionsModel) + + if err == nil { + return fmt.Errorf("subnet network acl attachment still exists: %s", rs.Primary.ID) + } + } + return nil +} + +func testAccCheckIBMISSubnetNetworkACLAttachmentExists(n, subnetNwACL string) resource.TestCheckFunc { + return func(s *terraform.State) error { + fmt.Println("siv ", s.RootModule().Resources) + rs, ok := s.RootModule().Resources[n] + + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return errors.New("No Record ID is set") + } + + sess, _ := testAccProvider.Meta().(ClientSession).VpcV1API() + getSubnetNetworkACLOptionsModel := &vpcv1.GetSubnetNetworkACLOptions{ + ID: &rs.Primary.ID, + } + foundSubnetNwACL, _, err := sess.GetSubnetNetworkACL(getSubnetNetworkACLOptionsModel) + if err != nil { + return err + } + subnetNwACL = *foundSubnetNwACL.ID + return nil + } +} + +func testAccCheckIBMISSubnetNetworkACLAttachmentConfig(nwaclname, vpcname, name, zone, cidr string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + + resource "ibm_is_network_acl" "isExampleACL" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + + rules { + name = "outbound" + action = "allow" + source = "0.0.0.0/0" + destination = "0.0.0.0/0" + direction = "outbound" + icmp { + code = 1 + type = 1 + } + # Optionals : + # port_max = + # port_min = + } + rules { + name = "inbound" + action = "allow" + source = "0.0.0.0/0" + destination = "0.0.0.0/0" + direction = "inbound" + icmp { + code = 1 + type = 1 + } + # Optionals : + # port_max = + # port_min = + } + } + + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + ipv4_cidr_block = "%s" + } + + resource "ibm_is_subnet_network_acl_attachment" attach { + depends_on = [ibm_is_network_acl.isExampleACL, ibm_is_subnet.testacc_subnet] + subnet = ibm_is_subnet.testacc_subnet.id + network_acl = ibm_is_network_acl.isExampleACL.id + } + + `, vpcname, nwaclname, name, zone, cidr) +} diff --git a/website/docs/r/is_subnet_network_acl_attachment.html.markdown b/website/docs/r/is_subnet_network_acl_attachment.html.markdown new file mode 100644 index 0000000000..62060716ce --- /dev/null +++ b/website/docs/r/is_subnet_network_acl_attachment.html.markdown @@ -0,0 +1,111 @@ +--- +layout: "ibm" +page_title: "IBM : subnet network acl attachment" +sidebar_current: "docs-ibm-resource-is-subnet-network-acl-attachment" +description: |- + Manages IBM Subnet Network ACL Attachment. +--- + +# ibm\_is_subnet_network_acl_attachment + +Provides a subnet network ACL attachment resource. This allows subnet network ACL attachment to be created, updated, and cancelled. + + +## Example Usage + +```hcl +resource "ibm_is_network_acl" "isExampleACL" { + name = "is-example-acl" + rules { + name = "outbound" + action = "allow" + source = "0.0.0.0/0" + destination = "0.0.0.0/0" + direction = "outbound" + icmp { + code = 1 + type = 1 + } + } + rules { + name = "inbound" + action = "allow" + source = "0.0.0.0/0" + destination = "0.0.0.0/0" + direction = "inbound" + icmp { + code = 1 + type = 1 + } + } +} + +resource "ibm_is_subnet" "testacc_subnet" { + name = "test_subnet" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "us-south-1" + ipv4_cidr_block = "192.168.0.0/1" + +} + +resource "ibm_is_subnet_network_acl_attachment" attach { + subnet = ibm_is_subnet.testacc_subnet.id + network_acl = ibm_is_network_acl.isExampleACL.id +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `subnet` - (Required, Forces new resource string) The subnet identifier. +* `network_acl` - (Required, string) The network ACL identity. + +## Attribute Reference + +The following attributes are exported: + +* `id` - The unique identifier for this network ACL. +* `name` - The user-defined name for this network ACL. +* `created_at` - The date and time that the network ACL was created. +* `crn` - The CRN for this network ACL. +* `href` - The URL for this network ACL. +* `resource_group` - The resource group for this network ACL. +* `rules` - The ordered rules for this network ACL. If no rules exist, all traffic will be denied. +Nested `rules` blocks have the following structure: + + * `action` - Whether to allow or deny matching traffic. + * `created_at` - The date and time that the rule was created + * `source` - The source CIDR block. The CIDR block 0.0.0.0/0 applies to all addresses. + * `destination` - The destination CIDR block. The CIDR block 0.0.0.0/0 applies to all addresses. + * `direction` - Whether the traffic to be matched is inbound or outbound. + * `href` - The URL for this Network ACL rule. + * `id` - The unique identifier for this Network ACL rule. + * `ip_version` - The IP version for this rule + * `name` - The user-defined name for this rule. + * `protocol` - The protocol to enforce. + * `icmp` - The protocol ICMP + * `code` - The ICMP traffic code to allow. If unspecified, all codes are allowed. This can only be specified if type is also specified. + * `type` - The ICMP traffic type to allow. If unspecified, all types are allowed by this rule. + * `tcp` - TCP protocol. + * `destination_port_max` - The inclusive upper bound of TCP destination port range. + * `destination_port_min` - The inclusive lower bound of TCP destination port range. + * `source_port_max` - The inclusive upper bound of TCP source port range. + * `source_port_min` - The inclusive lower bound of TCP source port range. + * `udp` - UDP protocol + * `destination_port_max` - The inclusive upper bound of UDP destination port range. + * `destination_port_min` - The inclusive lower bound of UDP destination port range. + * `source_port_max` - The inclusive upper bound of UDP source port range. + * `source_port_min` - The inclusive lower bound of UDP source port range. + * `subnets` - The subnets to which this network ACL is attached. + * `vpc` - The VPC this network ACL is a part of. + + +## Import + +ibm_is_subnet_network_acl_attachment can be imported using ID, eg + +``` +$ terraform import ibm_is_subnet_network_acl_attachment.example d7bec597-4726-451f-8a63-e62e6f19c32c +``` diff --git a/website/ibm.erb b/website/ibm.erb index 5951d4aed0..3be0101084 100644 --- a/website/ibm.erb +++ b/website/ibm.erb @@ -990,6 +990,9 @@