delete peer and interface

This commit is contained in:
Christoph 2023-12-24 16:50:49 +01:00
parent ef368c60ee
commit c645a3634a
2 changed files with 99 additions and 5 deletions

View File

@ -14,6 +14,7 @@ import (
var MikrotikDeviceType = "mikrotik" var MikrotikDeviceType = "mikrotik"
// WgMikrotikRepo implements all low-level WireGuard interactions using the Mikrotik REST API. // WgMikrotikRepo implements all low-level WireGuard interactions using the Mikrotik REST API.
// It uses the API endpoints described in https://help.mikrotik.com/docs/display/ROS/REST+API
type WgMikrotikRepo struct { type WgMikrotikRepo struct {
apiClient *http.Client apiClient *http.Client
baseUrl string baseUrl string
@ -114,6 +115,30 @@ func (w *WgMikrotikRepo) fetchObject(ctx context.Context, endpoint string) (map[
return restData, nil return restData, nil
} }
func (w *WgMikrotikRepo) deleteObject(ctx context.Context, endpoint string) error {
req, err := w.getRequest(ctx, http.MethodDelete, endpoint)
if err != nil {
return fmt.Errorf("failed to build REST request for endpoint %s: %w", endpoint, err)
}
response, err := w.apiClient.Do(req)
if err != nil {
return fmt.Errorf("failed to execute REST request %s: %w", req.URL.String(), err)
}
defer closeHttpResponse(response)
if response.StatusCode != http.StatusNoContent {
errData := parseResponseError(response)
return fmt.Errorf("REST request %s returned status %d: %v", req.URL.String(), response.StatusCode, errData)
}
return nil
}
func (w *WgMikrotikRepo) createObject(ctx context.Context, endpoint string, data map[string]string) (map[string]string, error) {
panic("implement me")
}
func (w *WgMikrotikRepo) GetInterfaces(ctx context.Context) ([]domain.PhysicalInterface, error) { func (w *WgMikrotikRepo) GetInterfaces(ctx context.Context) ([]domain.PhysicalInterface, error) {
restInterfaces, err := w.fetchList(ctx, "/interface/wireguard") restInterfaces, err := w.fetchList(ctx, "/interface/wireguard")
if err != nil { if err != nil {
@ -315,9 +340,51 @@ func (w *WgMikrotikRepo) SaveInterface(_ context.Context, id domain.InterfaceIde
panic("implement me") panic("implement me")
} }
func (w *WgMikrotikRepo) DeleteInterface(_ context.Context, id domain.InterfaceIdentifier) error { func (w *WgMikrotikRepo) DeleteInterface(ctx context.Context, id domain.InterfaceIdentifier) error {
//TODO implement me restIPv4, err := w.fetchList(ctx, "/ip/address?interface="+string(id))
panic("implement me") if err != nil {
return fmt.Errorf("failed to get IPv4 addresses: %w", err)
}
for _, addr := range restIPv4 {
err = w.deleteObject(ctx, "/ip/address/"+addr[".id"])
if err != nil {
return fmt.Errorf("failed to delete IPv4 address %s: %w", addr["address"], err)
}
}
restIPv6, err := w.fetchList(ctx, "/ipv6/address?interface="+string(id))
if err != nil {
return fmt.Errorf("failed to get IPv6 addresses: %w", err)
}
for _, addr := range restIPv6 {
err = w.deleteObject(ctx, "/ipv6/address/"+addr[".id"])
if err != nil {
return fmt.Errorf("failed to delete IPv6 address %s: %w", addr["address"], err)
}
}
restPeers, err := w.fetchList(ctx, "/interface/wireguard/peers?interface="+string(id))
if err != nil {
return fmt.Errorf("failed to get peers for %s: %w", id, err)
}
for _, restPeer := range restPeers {
err = w.DeletePeer(ctx, id, domain.PeerIdentifier(restPeer["public-key"]))
if err != nil {
return fmt.Errorf("failed to delete peer %s: %w", restPeer["public-key"], err)
}
}
restInterface, err := w.fetchObject(ctx, "/interface/wireguard/"+string(id)+"?.proplist=.id")
if err != nil {
return fmt.Errorf("failed to get interface %s: %w", id, err)
}
err = w.deleteObject(ctx, "/interface/wireguard/"+restInterface[".id"])
if err != nil {
return fmt.Errorf("failed to delete interface %s: %w", id, err)
}
return nil
} }
func (w *WgMikrotikRepo) SavePeer(_ context.Context, deviceId domain.InterfaceIdentifier, id domain.PeerIdentifier, updateFunc func(pp *domain.PhysicalPeer) (*domain.PhysicalPeer, error)) error { func (w *WgMikrotikRepo) SavePeer(_ context.Context, deviceId domain.InterfaceIdentifier, id domain.PeerIdentifier, updateFunc func(pp *domain.PhysicalPeer) (*domain.PhysicalPeer, error)) error {
@ -326,6 +393,21 @@ func (w *WgMikrotikRepo) SavePeer(_ context.Context, deviceId domain.InterfaceId
} }
func (w *WgMikrotikRepo) DeletePeer(_ context.Context, deviceId domain.InterfaceIdentifier, id domain.PeerIdentifier) error { func (w *WgMikrotikRepo) DeletePeer(_ context.Context, deviceId domain.InterfaceIdentifier, id domain.PeerIdentifier) error {
//TODO implement me restPeers, err := w.fetchList(context.Background(), "/interface/wireguard/peers?interface="+string(deviceId)+"&public-key="+string(id)+"&.proplist=.id")
panic("implement me") if err != nil {
return fmt.Errorf("failed to get peer %s on device %s: %w", id, deviceId, err)
}
if len(restPeers) != 1 {
return fmt.Errorf("failed to get peer %s on device %s: got %d entries", id, deviceId, len(restPeers))
}
restPeer := restPeers[0]
err = w.deleteObject(context.Background(), "/interface/wireguard/peers/"+restPeer[".id"])
if err != nil {
return fmt.Errorf("failed to delete peer %s on device %s: %w", id, deviceId, err)
}
return nil
} }

View File

@ -42,3 +42,15 @@ func TestWgMikrotikRepo_GetPeer(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equalf(t, domain.PeerIdentifier("Ytfq6plqkOo95HAUYGrjiG3GU352NahLYLnE1cItDkI="), got.Identifier, "GetPeer()") assert.Equalf(t, domain.PeerIdentifier("Ytfq6plqkOo95HAUYGrjiG3GU352NahLYLnE1cItDkI="), got.Identifier, "GetPeer()")
} }
func TestWgMikrotikRepo_DeleteInterface(t *testing.T) {
w := NewWgMikrotikRepo(MikrotikUrl, MikrotikUser, MikrotikPass)
err := w.DeleteInterface(context.Background(), "wgTest")
assert.NoError(t, err)
}
func TestWgMikrotikRepo_DeletePeer(t *testing.T) {
w := NewWgMikrotikRepo(MikrotikUrl, MikrotikUser, MikrotikPass)
err := w.DeletePeer(context.Background(), "wgTest", "qlFPZUOwt+SheTatRdIr0yGrTffyPEvzE3EeKVArgn8=")
assert.NoError(t, err)
}