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

[Feature] Add Interface Wireguard Peer resource type #176

Merged
merged 6 commits into from
Aug 11, 2023
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
91 changes: 91 additions & 0 deletions client/interface_wireguard_peer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package client

import (
"github.com/go-routeros/routeros"
)

type InterfaceWireguardPeer struct {
Id string `mikrotik:".id"`
AllowedAddress string `mikrotik:"allowed-address"`
Comment string `mikrotik:"comment"`
Disabled bool `mikrotik:"disabled"`
EndpointAddress string `mikrotik:"endpoint-address"`
EndpointPort int64 `mikrotik:"endpoint-port"`
Interface string `mikrotik:"interface"`
PersistentKeepalive int64 `mikrotik:"persistent-keepalive"`
PresharedKey string `mikrotik:"preshared-key"`
PublicKey string `mikrotik:"public-key"`
}

func (i *InterfaceWireguardPeer) ActionToCommand(action Action) string {
return map[Action]string{
Add: "/interface/wireguard/peers/add",
Find: "/interface/wireguard/peers/print",
List: "/interface/wireguard/peers/print",
Update: "/interface/wireguard/peers/set",
Delete: "/interface/wireguard/peers/remove",
}[action]
}

func (i *InterfaceWireguardPeer) IDField() string {
return ".id"
}

func (i *InterfaceWireguardPeer) ID() string {
return i.Id
}

func (i *InterfaceWireguardPeer) SetID(id string) {
i.Id = id
}

func (i *InterfaceWireguardPeer) AfterAddHook(r *routeros.Reply) {
i.Id = r.Done.Map["ret"]
}

func (i *InterfaceWireguardPeer) FindField() string {
return "interface"
}

func (i *InterfaceWireguardPeer) FindFieldValue() string {
return i.Interface
}

func (i *InterfaceWireguardPeer) DeleteField() string {
return "numbers"
}

func (i *InterfaceWireguardPeer) DeleteFieldValue() string {
return i.Id
}

func (client Mikrotik) AddInterfaceWireguardPeer(i *InterfaceWireguardPeer) (*InterfaceWireguardPeer, error) {
res, err := client.Add(i)
if err != nil {
return nil, err
}

return res.(*InterfaceWireguardPeer), nil
}

func (client Mikrotik) FindInterfaceWireguardPeer(interfaceName string) (*InterfaceWireguardPeer, error) {
res, err := client.Find(&InterfaceWireguardPeer{Interface: interfaceName})
if err != nil {
return nil, err
}

return res.(*InterfaceWireguardPeer), nil
}

func (client Mikrotik) UpdateInterfaceWireguardPeer(i *InterfaceWireguardPeer) (*InterfaceWireguardPeer, error) {
res, err := client.Update(i)
if err != nil {
return nil, err
}

return res.(*InterfaceWireguardPeer), nil
}

func (client Mikrotik) DeleteInterfaceWireguardPeer(id string) error {
return client.Delete(&InterfaceWireguardPeer{Id: id})
}
79 changes: 79 additions & 0 deletions client/interface_wireguard_peer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package client

import (
"reflect"
"testing"

"github.com/stretchr/testify/require"
)

func TestFindInterfaceWireguardPeer_onNonExistantInterfacePeer(t *testing.T) {
SkipIfRouterOSV6OrEarlier(t, sysResources)
c := NewClient(GetConfigFromEnv())

interfaceName := "Interface peer does not exist"
_, err := c.FindInterfaceWireguardPeer(interfaceName)

require.Truef(t, IsNotFoundError(err),
"Expecting to receive NotFound error for Interface peer `%q`, instead error was nil.", interfaceName)
}

func TestInterfaceWireguardPeer_Crud(t *testing.T) {
SkipIfRouterOSV6OrEarlier(t, sysResources)
c := NewClient(GetConfigFromEnv())

name := "new_interface_wireguard"
interfaceWireguard := &InterfaceWireguard{
Name: name,
Disabled: false,
ListenPort: 10000,
Mtu: 10001,
PrivateKey: "YOi0P0lTTiN8hAQvuRET23Srb+U7C52iOZokj0CCSkM=",
Comment: "new interface from test",
}

createdInterface, err := c.Add(interfaceWireguard)
if err != nil {
t.Errorf("expected no error, got %v", err)
return
}
defer func() {
err = c.Delete(interfaceWireguard)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
}()

interfaceWireguardPeer := &InterfaceWireguardPeer{
Interface: createdInterface.(*InterfaceWireguard).Name,
Disabled: false,
Comment: "new interface from test",
}

created, err := c.Add(interfaceWireguardPeer)
if err != nil {
t.Errorf("expected no error, got %v", err)
return
}
defer func() {
err = c.Delete(interfaceWireguardPeer)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
}()
findInterface := &InterfaceWireguardPeer{}
findInterface.Interface = createdInterface.(*InterfaceWireguard).Name
found, err := c.Find(findInterface)
if err != nil {
t.Errorf("expected no error, got %v", err)
return
}

if _, ok := found.(Resource); !ok {
t.Error("expected found resource to implement Resource interface, but it doesn't")
return
}
if !reflect.DeepEqual(created, found) {
t.Error("expected created and found resources to be equal, but they aren't")
}
}
28 changes: 28 additions & 0 deletions docs/resources/interface_wireguard_peer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# mikrotik_interface_wireguard_peer (Resource)
Creates a Mikrotik Interface Wireguard Peer only supported by RouterOS v7+.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `interface` (String) Name of the WireGuard interface the peer belongs to.

### Optional

- `allowed_address` (String) List of IP (v4 or v6) addresses with CIDR masks from which incoming traffic for this peer is allowed and to which outgoing traffic for this peer is directed. The catch-all 0.0.0.0/0 may be specified for matching all IPv4 addresses, and ::/0 may be specified for matching all IPv6 addresses.
- `comment` (String) Short description of the peer.
- `disabled` (Boolean) Boolean for whether or not the interface peer is disabled.
- `endpoint_address` (String) An endpoint IP or hostname can be left blank to allow remote connection from any address.
- `endpoint_port` (Number) An endpoint port can be left blank to allow remote connection from any port.
- `persistent_keepalive` (Number) A seconds interval, between 1 and 65535 inclusive, of how often to send an authenticated empty packet to the peer for the purpose of keeping a stateful firewall or NAT mapping valid persistently. For example, if the interface very rarely sends traffic, but it might at anytime receive traffic from a peer, and it is behind NAT, the interface might benefit from having a persistent keepalive interval of 25 seconds.
- `preshared_key` (String) A base64 preshared key. Optional, and may be omitted. This option adds an additional layer of symmetric-key cryptography to be mixed into the already existing public-key cryptography, for post-quantum resistance.
- `public_key` (String) The remote peer's calculated public key.

### Read-Only

- `id` (String) Identifier of this resource assigned by RouterOS


1 change: 1 addition & 0 deletions mikrotik/provider_framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func (p *ProviderFramework) Resources(ctx context.Context) []func() resource.Res
NewInterfaceWireguardResource,
NewSchedulerResource,
NewScriptResource,
NewInterfaceWireguardPeerResource,
}
}

Expand Down
Loading