Skip to content
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
70 changes: 70 additions & 0 deletions docs/resources/vpc_acl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
subcategory: "VPC"
page_title: "Scaleway: scaleway_vpc_acl"
---

# Resource: scaleway_vpc_acl

Creates and manages Scaleway VPC ACLs.

## Example Usage

### Basic

```terraform
resource "scaleway_vpc" "vpc01" {
name = "tf-vpc-acl"
}

resource "scaleway_vpc_acl" "acl01" {
vpc_id = scaleway_vpc.vpc01.id
is_ipv6 = false
rules {
protocol = "TCP"
src_port_low = 0
src_port_high = 0
dst_port_low = 80
dst_port_high = 80
source = "0.0.0.0/0"
destination = "0.0.0.0/0"
description = "Allow HTTP traffic from any source"
action = "accept"
}
default_policy = "drop"
}
```

## Argument Reference

The following arguments are supported:

- `vpc_id` - (Required) The VPC ID the ACL belongs to.
- `default_policy` - (Required) The action to take for packets which do not match any rules.
- `is_ipv6` - (Optional) Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type.
- `rules` - (Optional) The list of Network ACL rules.
- `protocol` - (Optional) The protocol to which this rule applies. Default value: ANY.
- `source` - (Optional) The Source IP range to which this rule applies (CIDR notation with subnet mask).
- `src_port_low` - (Optional) The starting port of the source port range to which this rule applies (inclusive).
- `src_port_high` - (Optional) The ending port of the source port range to which this rule applies (inclusive).
- `destination` - (Optional) The destination IP range to which this rule applies (CIDR notation with subnet mask).
- `dst_port_low` - (Optional) The starting port of the destination port range to which this rule applies (inclusive).
- `dst_port_high` - (Optional) The ending port of the destination port range to which this rule applies (inclusive).
- `action` - (Optional) The policy to apply to the packet.
- `description` - (Optional) The rule description.
- `region` - (Defaults to [provider](../index.md#region) `region`) The [region](../guides/regions_and_zones.md#regions) of the ACL.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:

- `id` - The ID of the ACL.

~> **Important:** ACLs' IDs are [regional](../guides/regions_and_zones.md#resource-ids), which means they are of the form `{region}/{id}`, e.g. `fr-par/11111111-1111-1111-1111-111111111111

## Import

ACLs can be imported using `{region}/{id}`, e.g.

```bash
terraform import scaleway_vpc_acl.main fr-par/11111111-1111-1111-1111-111111111111
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ func Provider(config *Config) plugin.ProviderFunc {
"scaleway_tem_domain_validation": tem.ResourceDomainValidation(),
"scaleway_tem_webhook": tem.ResourceWebhook(),
"scaleway_vpc": vpc.ResourceVPC(),
"scaleway_vpc_acl": vpc.ResourceACL(),
"scaleway_vpc_gateway_network": vpcgw.ResourceNetwork(),
"scaleway_vpc_private_network": vpc.ResourcePrivateNetwork(),
"scaleway_vpc_public_gateway": vpcgw.ResourcePublicGateway(),
Expand Down
211 changes: 211 additions & 0 deletions internal/services/vpc/acl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package vpc

import (
"context"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/vpc/v2"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
)

func ResourceACL() *schema.Resource {
return &schema.Resource{
CreateContext: ResourceVPCACLCreate,
ReadContext: ResourceVPCACLRead,
UpdateContext: ResourceVPCACLUpdate,
DeleteContext: ResourceVPCACLDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
SchemaVersion: 0,
Schema: map[string]*schema.Schema{
"vpc_id": {
Type: schema.TypeString,
Required: true,
Description: "The VPC in which to create the ACL rule",
},
"default_policy": {
Type: schema.TypeString,
Required: true,
Description: "The action to take for packets which do not match any rules",
ValidateDiagFunc: verify.ValidateEnum[vpc.Action](),
},
"is_ipv6": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Defines whether this set of ACL rules is for IPv6 (false = IPv4). Each Network ACL can have rules for only one IP type",
},
"rules": {
Type: schema.TypeList,
Required: true,
Description: "The list of Network ACL rules",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"protocol": {
Type: schema.TypeString,
Optional: true,
Default: "ANY",
Description: "The protocol to which this rule applies. Default value: ANY",
ValidateDiagFunc: verify.ValidateEnum[vpc.ACLRuleProtocol](),
},
"source": {
Type: schema.TypeString,
Optional: true,
Description: "Source IP range to which this rule applies (CIDR notation with subnet mask)",
},
"src_port_low": {
Type: schema.TypeInt,
Optional: true,
Description: "Starting port of the source port range to which this rule applies (inclusive)",
},
"src_port_high": {
Type: schema.TypeInt,
Optional: true,
Description: "Ending port of the source port range to which this rule applies (inclusive)",
},
"destination": {
Type: schema.TypeString,
Optional: true,
Description: "Destination IP range to which this rule applies (CIDR notation with subnet mask)",
},
"dst_port_low": {
Type: schema.TypeInt,
Optional: true,
Description: "Starting port of the destination port range to which this rule applies (inclusive)",
},
"dst_port_high": {
Type: schema.TypeInt,
Optional: true,
Description: "Ending port of the destination port range to which this rule applies (inclusive)",
},
"action": {
Type: schema.TypeString,
Optional: true,
Description: "The policy to apply to the packet",
ValidateDiagFunc: verify.ValidateEnum[vpc.Action](),
},
"description": {
Type: schema.TypeString,
Optional: true,
Description: "The rule description",
},
},
},
},
"region": regional.Schema(),
},
}
}

func ResourceVPCACLCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vpcAPI, region, err := vpcAPIWithRegion(d, m)
if err != nil {
return diag.FromErr(err)
}

req := &vpc.SetACLRequest{
VpcID: locality.ExpandID(d.Get("vpc_id").(string)),
IsIPv6: d.Get("is_ipv6").(bool),
DefaultPolicy: vpc.Action(d.Get("default_policy").(string)),
Region: region,
}

expandedRules, err := expandACLRules(d.Get("rules"))
if err != nil {
return diag.FromErr(err)
}

if d.Get("rules") != nil {
req.Rules = expandedRules
}

_, err = vpcAPI.SetACL(req, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

d.SetId(regional.NewIDString(region, regional.ExpandID(d.Get("vpc_id").(string)).ID))

return ResourceVPCACLRead(ctx, d, m)
}

func ResourceVPCACLRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
if err != nil {
return diag.FromErr(err)
}

acl, err := vpcAPI.GetACL(&vpc.GetACLRequest{
VpcID: locality.ExpandID(ID),
Region: region,
IsIPv6: d.Get("is_ipv6").(bool),
}, scw.WithContext(ctx))
if err != nil {
if httperrors.Is404(err) {
d.SetId("")

return nil
}

return diag.FromErr(err)
}

_ = d.Set("rules", flattenACLRules(acl.Rules))
_ = d.Set("default_policy", acl.DefaultPolicy.String())

return nil
}

func ResourceVPCACLUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
if err != nil {
return diag.FromErr(err)
}

req := &vpc.SetACLRequest{
VpcID: locality.ExpandID(ID),
IsIPv6: d.Get("is_ipv6").(bool),
DefaultPolicy: vpc.Action(d.Get("default_policy").(string)),
Region: region,
}

expandedRules, err := expandACLRules(d.Get("rules"))
if err != nil {
return diag.FromErr(err)
}

if d.Get("rules") != nil {
req.Rules = expandedRules
}

_, err = vpcAPI.SetACL(req, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

return ResourceVPCACLRead(ctx, d, m)
}

func ResourceVPCACLDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
vpcAPI, region, ID, err := NewAPIWithRegionAndID(m, d.Id())
if err != nil {
return diag.FromErr(err)
}

_, err = vpcAPI.SetACL(&vpc.SetACLRequest{
VpcID: locality.ExpandID(ID),
Region: region,
DefaultPolicy: "drop",
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

return nil
}
Loading
Loading