Skip to content

Commit

Permalink
fix: Firewall filter rules order (#314)
Browse files Browse the repository at this point in the history
* fix: Firewall filter rules order
Fixes  #293
Thanks to @Toalaah

* fix: Resource path
  • Loading branch information
vaerh authored Dec 6, 2023
1 parent dcf849e commit 3d32136
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 0 deletions.
79 changes: 79 additions & 0 deletions examples/resources/routeros_move_items/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
variable "rule" {
type = list(object({
chain = string
action = string
connection_state = optional(string)
in_interface_list = optional(string, "all")
out_interface_list = optional(string)
src_address = optional(string, "0.0.0.0/0")
dst_address = optional(string)
src_port = optional(string)
dst_port = optional(string)
protocol = optional(string)
comment = optional(string, "(terraform-defined)")
log = optional(bool, false)
disabled = optional(bool, true)
}))

default = [
{ chain = "input", action = "accept", comment = "00" },
{ chain = "input", action = "accept", comment = "01" },
{ chain = "input", action = "accept", comment = "02" },
{ chain = "input", action = "accept", comment = "03" },
{ chain = "input", action = "accept", comment = "04" },
{ chain = "input", action = "accept", comment = "05" },
{ chain = "input", action = "accept", comment = "06" },
{ chain = "input", action = "accept", comment = "07" },
{ chain = "input", action = "accept", comment = "08" },
{ chain = "input", action = "accept", comment = "09" },
{ chain = "input", action = "accept", comment = "10" },
{ chain = "input", action = "accept", comment = "11" },
{ chain = "input", action = "accept", comment = "12" },
{ chain = "input", action = "accept", comment = "13" },
{ chain = "input", action = "accept", comment = "14" },
{ chain = "input", action = "accept", comment = "15" },
{ chain = "input", action = "accept", comment = "16" },
{ chain = "input", action = "accept", comment = "17" },
{ chain = "input", action = "accept", comment = "18" },
{ chain = "input", action = "accept", comment = "19" },
{ chain = "input", action = "accept", comment = "20" },
{ chain = "input", action = "accept", comment = "21" },
{ chain = "input", action = "accept", comment = "22" },
{ chain = "input", action = "accept", comment = "23" },
{ chain = "input", action = "accept", comment = "24" },
{ chain = "input", action = "accept", comment = "25" },
{ chain = "input", action = "accept", comment = "26" },
{ chain = "input", action = "accept", comment = "27" },
{ chain = "input", action = "accept", comment = "28" },
{ chain = "input", action = "accept", comment = "29" },
{ chain = "input", action = "accept", comment = "30" },
{ chain = "input", action = "accept", comment = "31" },
]
}

locals {
# https://discuss.hashicorp.com/t/does-map-sort-keys/12056/2
# Map keys are always iterated in lexicographical order!
rule_map = { for idx, rule in var.rule : format("%03d", idx) => rule }
}

resource "routeros_ip_firewall_filter" "rules" {
for_each = local.rule_map
chain = each.value.chain
action = each.value.action
comment = each.value.comment
log = each.value.log
disabled = each.value.disabled
connection_state = each.value.connection_state
in_interface_list = each.value.in_interface_list
src_address = each.value.src_address
dst_port = each.value.dst_port
protocol = each.value.protocol
}

resource "routeros_move_items" "fw_rules" {
# resource_name = "routeros_ip_firewall_filter"
resource_path = "/ip/firewall/filter"
sequence = [for i, _ in local.rule_map : routeros_ip_firewall_filter.rules[i].id]
depends_on = [routeros_ip_firewall_filter.rules]
}
1 change: 1 addition & 0 deletions routeros/mikrotik_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (
crudSign
crudRemove
crudRevoke
crudMove
)

func NewClient(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
Expand Down
1 change: 1 addition & 0 deletions routeros/mikrotik_client_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var (
crudSign: "/sign",
crudRemove: "/remove",
crudRevoke: "/issued-revoke",
crudMove: "/move",
}
)

Expand Down
1 change: 1 addition & 0 deletions routeros/mikrotik_client_rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var (
crudSign: "POST",
crudRemove: "POST",
crudRevoke: "POST",
crudMove: "POST",
}
)

Expand Down
2 changes: 2 additions & 0 deletions routeros/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ func Provider() *schema.Provider {
"routeros_user_manager_user": ResourceUserManagerUser(),
"routeros_user_manager_user_group": ResourceUserManagerUserGroup(),
"routeros_user_manager_user_profile": ResourceUserManagerUserProfile(),

"routeros_move_items": ResourceMoveItems(),
},
DataSourcesMap: map[string]*schema.Resource{
"routeros_firewall": DatasourceFirewall(),
Expand Down
121 changes: 121 additions & 0 deletions routeros/resource_move.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package routeros

import (
"context"
"fmt"
"regexp"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func ResourceMoveItems() *schema.Resource {
resSchema := map[string]*schema.Schema{
MetaResourcePath: PropResourcePath("/path"),
MetaId: PropId(Id),

"resource_name": {
Type: schema.TypeString,
Optional: true,
Description: "Resource name in the notation ```routeros_ip_firewall_filter```.",
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^routeros(_\w+)+$`), ""),
AtLeastOneOf: []string{"resource_name", "resource_path"},
},
"resource_path": {
Type: schema.TypeString,
Optional: true,
Description: "URL path of the resource in the notation ```/ip/firewall/filter```.",
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^(/\w+)+$`), ""),
AtLeastOneOf: []string{"resource_name", "resource_path"},
},
"sequence": {
Type: schema.TypeList,
Required: true,
Description: "List identifiers in the required sequence.",
Elem: &schema.Schema{
Type: schema.TypeString,
MinItems: 2,
},
},
}
resRead := func(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
path, ok := d.GetOk("resource_path")
if !ok {
path = d.Get("resource_name")
path = strings.TrimPrefix(path.(string), "routeros_")
path = strings.ReplaceAll(path.(string), "_", "/")
}

res, err := ReadItems(nil, path.(string), m.(Client))
if err != nil {
ColorizedDebug(ctx, fmt.Sprintf(ErrorMsgGet, err))
return diag.FromErr(err)
}

// Resource not found.
if len(*res) == 0 {
d.SetId("")
return nil
}

var conf = make(map[string]struct{})
for _, v := range d.Get("sequence").([]any) {
conf[v.(string)] = struct{}{}
}

var list []string
for _, r := range *res {
if id, ok := r[".id"]; ok {
if _, ok := conf[id]; ok {
list = append(list, id)
}
}
}

d.Set("sequence", list)
return nil
}

resCreateUpdate := func(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var list []string
for _, v := range d.Get("sequence").([]any) {
list = append(list, v.(string))
}

item := MikrotikItem{
"numbers": strings.Join(list[:len(list)-1], ","),
"destination": list[len(list)-1],
}

path, ok := d.GetOk("resource_path")
if !ok {
path = d.Get("resource_name")
path = strings.TrimPrefix(path.(string), "routeros_")
path = strings.ReplaceAll(path.(string), "_", "/")
}

if m.(Client).GetTransport() == TransportREST {
path = path.(string) + "/move"
}
err := m.(Client).SendRequest(crudMove, &URL{Path: path.(string)}, item, nil)
if err != nil {
ColorizedDebug(ctx, fmt.Sprintf(ErrorMsgPut, err))
return diag.FromErr(err)
}

d.SetId(strings.ReplaceAll(strings.TrimLeft(path.(string), "/"), "/", "."))

return resRead(ctx, d, m)
}

return &schema.Resource{
CreateContext: resCreateUpdate,
ReadContext: resRead,
UpdateContext: resCreateUpdate,
DeleteContext: DefaultSystemDelete(resSchema),

Schema: resSchema,
}
}

0 comments on commit 3d32136

Please sign in to comment.