mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-25 01:23:22 +01:00
Feature/add nameservers API endpoint (#491)
Add nameservers endpoint and Open API definition updated open api generator cli
This commit is contained in:
parent
369a7ef345
commit
b4e03f4616
@ -127,6 +127,7 @@ func (g *NameServerGroup) Copy() *NameServerGroup {
|
||||
Description: g.Description,
|
||||
NameServers: g.NameServers,
|
||||
Groups: g.Groups,
|
||||
Enabled: g.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,3 +3,5 @@ generate:
|
||||
models: true
|
||||
embedded-spec: false
|
||||
output: types.gen.go
|
||||
compatibility:
|
||||
always-prefix-enum-values: true
|
@ -11,6 +11,6 @@ fi
|
||||
old_pwd=$(pwd)
|
||||
script_path=$(dirname $(realpath "$0"))
|
||||
cd "$script_path"
|
||||
go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.11.0
|
||||
go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@4a1477f6a8ba6ca8115cc23bb2fb67f0b9fca18e
|
||||
oapi-codegen --config cfg.yaml openapi.yml
|
||||
cd "$old_pwd"
|
@ -16,6 +16,8 @@ tags:
|
||||
description: Interact with and view information about rules.
|
||||
- name: Routes
|
||||
description: Interact with and view information about routes.
|
||||
- name: DNS
|
||||
description: Interact with and view information about DNS configuration.
|
||||
components:
|
||||
schemas:
|
||||
User:
|
||||
@ -373,6 +375,76 @@ components:
|
||||
enum: [ "network","network_id","description","enabled","peer","metric","masquerade" ]
|
||||
required:
|
||||
- path
|
||||
Nameserver:
|
||||
type: object
|
||||
properties:
|
||||
ip:
|
||||
description: Nameserver IP
|
||||
type: string
|
||||
ns_type:
|
||||
description: Nameserver Type
|
||||
type: string
|
||||
enum: ["udp"]
|
||||
port:
|
||||
description: Nameserver Port
|
||||
type: integer
|
||||
required:
|
||||
- ip
|
||||
- ns_type
|
||||
- port
|
||||
NameserverGroupRequest:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
description: Nameserver group name
|
||||
type: string
|
||||
maxLength: 40
|
||||
minLength: 1
|
||||
description:
|
||||
description: Nameserver group description
|
||||
type: string
|
||||
nameservers:
|
||||
description: Nameserver group
|
||||
minLength: 1
|
||||
maxLength: 2
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Nameserver'
|
||||
enabled:
|
||||
description: Nameserver group status
|
||||
type: boolean
|
||||
groups:
|
||||
description: Nameserver group tag groups
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- description
|
||||
- nameservers
|
||||
- enabled
|
||||
- groups
|
||||
NameserverGroup:
|
||||
allOf:
|
||||
- type: object
|
||||
properties:
|
||||
id:
|
||||
description: Nameserver group ID
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- $ref: '#/components/schemas/NameserverGroupRequest'
|
||||
NameserverGroupPatchOperation:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/PatchMinimum'
|
||||
- type: object
|
||||
properties:
|
||||
path:
|
||||
description: Nameserver group field to update in form /<field>
|
||||
type: string
|
||||
enum: [ "name","description","enabled","groups","nameservers" ]
|
||||
required:
|
||||
- path
|
||||
|
||||
responses:
|
||||
not_found:
|
||||
@ -1238,6 +1310,176 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
description: The Route ID
|
||||
responses:
|
||||
'200':
|
||||
description: Delete status code
|
||||
content: { }
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/dns/nameservers:
|
||||
get:
|
||||
summary: Returns a list of all Nameserver Groups
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
responses:
|
||||
'200':
|
||||
description: A JSON Array of Nameserver Groups
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/NameserverGroup'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Creates a Nameserver Group
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
requestBody:
|
||||
description: New Nameserver Groups request
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: '#/components/schemas/NameserverGroupRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: A Nameserver Groups Object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NameserverGroup'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
|
||||
/api/dns/nameservers/{id}:
|
||||
get:
|
||||
summary: Get information about a Nameserver Groups
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The Nameserver Group ID
|
||||
responses:
|
||||
'200':
|
||||
description: A Nameserver Group object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NameserverGroup'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update/Replace a Nameserver Group
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The Nameserver Group ID
|
||||
requestBody:
|
||||
description: Update Nameserver Group request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NameserverGroupRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: A Nameserver Group object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NameserverGroup'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
patch:
|
||||
summary: Update information about a Nameserver Group
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The Nameserver Group ID
|
||||
requestBody:
|
||||
description: Update Nameserver Group request using a list of json patch objects
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/NameserverGroupPatchOperation'
|
||||
responses:
|
||||
'200':
|
||||
description: A Nameserver Group object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NameserverGroup'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Nameserver Group
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The Nameserver Group ID
|
||||
responses:
|
||||
'200':
|
||||
description: Delete status code
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Package api provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/deepmap/oapi-codegen version v1.11.0 DO NOT EDIT.
|
||||
// Code generated by github.com/deepmap/oapi-codegen version v1.11.1-0.20220912230023-4a1477f6a8ba DO NOT EDIT.
|
||||
package api
|
||||
|
||||
import (
|
||||
@ -24,6 +24,27 @@ const (
|
||||
GroupPatchOperationPathPeers GroupPatchOperationPath = "peers"
|
||||
)
|
||||
|
||||
// Defines values for NameserverNsType.
|
||||
const (
|
||||
NameserverNsTypeUdp NameserverNsType = "udp"
|
||||
)
|
||||
|
||||
// Defines values for NameserverGroupPatchOperationOp.
|
||||
const (
|
||||
NameserverGroupPatchOperationOpAdd NameserverGroupPatchOperationOp = "add"
|
||||
NameserverGroupPatchOperationOpRemove NameserverGroupPatchOperationOp = "remove"
|
||||
NameserverGroupPatchOperationOpReplace NameserverGroupPatchOperationOp = "replace"
|
||||
)
|
||||
|
||||
// Defines values for NameserverGroupPatchOperationPath.
|
||||
const (
|
||||
NameserverGroupPatchOperationPathDescription NameserverGroupPatchOperationPath = "description"
|
||||
NameserverGroupPatchOperationPathEnabled NameserverGroupPatchOperationPath = "enabled"
|
||||
NameserverGroupPatchOperationPathGroups NameserverGroupPatchOperationPath = "groups"
|
||||
NameserverGroupPatchOperationPathName NameserverGroupPatchOperationPath = "name"
|
||||
NameserverGroupPatchOperationPathNameservers NameserverGroupPatchOperationPath = "nameservers"
|
||||
)
|
||||
|
||||
// Defines values for PatchMinimumOp.
|
||||
const (
|
||||
PatchMinimumOpAdd PatchMinimumOp = "add"
|
||||
@ -68,322 +89,397 @@ const (
|
||||
|
||||
// Group defines model for Group.
|
||||
type Group struct {
|
||||
// Group ID
|
||||
// Id Group ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// Group Name identifier
|
||||
// Name Group Name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// List of peers object
|
||||
// Peers List of peers object
|
||||
Peers []PeerMinimum `json:"peers"`
|
||||
|
||||
// Count of peers associated to the group
|
||||
// PeersCount Count of peers associated to the group
|
||||
PeersCount int `json:"peers_count"`
|
||||
}
|
||||
|
||||
// GroupMinimum defines model for GroupMinimum.
|
||||
type GroupMinimum struct {
|
||||
// Group ID
|
||||
// Id Group ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// Group Name identifier
|
||||
// Name Group Name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// Count of peers associated to the group
|
||||
// PeersCount Count of peers associated to the group
|
||||
PeersCount int `json:"peers_count"`
|
||||
}
|
||||
|
||||
// GroupPatchOperation defines model for GroupPatchOperation.
|
||||
type GroupPatchOperation struct {
|
||||
// Patch operation type
|
||||
// Op Patch operation type
|
||||
Op GroupPatchOperationOp `json:"op"`
|
||||
|
||||
// Group field to update in form /<field>
|
||||
// Path Group field to update in form /<field>
|
||||
Path GroupPatchOperationPath `json:"path"`
|
||||
|
||||
// Values to be applied
|
||||
// Value Values to be applied
|
||||
Value []string `json:"value"`
|
||||
}
|
||||
|
||||
// Patch operation type
|
||||
// GroupPatchOperationOp Patch operation type
|
||||
type GroupPatchOperationOp string
|
||||
|
||||
// Group field to update in form /<field>
|
||||
// GroupPatchOperationPath Group field to update in form /<field>
|
||||
type GroupPatchOperationPath string
|
||||
|
||||
// Nameserver defines model for Nameserver.
|
||||
type Nameserver struct {
|
||||
// Ip Nameserver IP
|
||||
Ip string `json:"ip"`
|
||||
|
||||
// NsType Nameserver Type
|
||||
NsType NameserverNsType `json:"ns_type"`
|
||||
|
||||
// Port Nameserver Port
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
// NameserverNsType Nameserver Type
|
||||
type NameserverNsType string
|
||||
|
||||
// NameserverGroup defines model for NameserverGroup.
|
||||
type NameserverGroup struct {
|
||||
// Description Nameserver group description
|
||||
Description string `json:"description"`
|
||||
|
||||
// Enabled Nameserver group status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Groups Nameserver group tag groups
|
||||
Groups []string `json:"groups"`
|
||||
|
||||
// Id Nameserver group ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// Name Nameserver group name
|
||||
Name string `json:"name"`
|
||||
|
||||
// Nameservers Nameserver group
|
||||
Nameservers []Nameserver `json:"nameservers"`
|
||||
}
|
||||
|
||||
// NameserverGroupPatchOperation defines model for NameserverGroupPatchOperation.
|
||||
type NameserverGroupPatchOperation struct {
|
||||
// Op Patch operation type
|
||||
Op NameserverGroupPatchOperationOp `json:"op"`
|
||||
|
||||
// Path Nameserver group field to update in form /<field>
|
||||
Path NameserverGroupPatchOperationPath `json:"path"`
|
||||
|
||||
// Value Values to be applied
|
||||
Value []string `json:"value"`
|
||||
}
|
||||
|
||||
// NameserverGroupPatchOperationOp Patch operation type
|
||||
type NameserverGroupPatchOperationOp string
|
||||
|
||||
// NameserverGroupPatchOperationPath Nameserver group field to update in form /<field>
|
||||
type NameserverGroupPatchOperationPath string
|
||||
|
||||
// NameserverGroupRequest defines model for NameserverGroupRequest.
|
||||
type NameserverGroupRequest struct {
|
||||
// Description Nameserver group description
|
||||
Description string `json:"description"`
|
||||
|
||||
// Enabled Nameserver group status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Groups Nameserver group tag groups
|
||||
Groups []string `json:"groups"`
|
||||
|
||||
// Name Nameserver group name
|
||||
Name string `json:"name"`
|
||||
|
||||
// Nameservers Nameserver group
|
||||
Nameservers []Nameserver `json:"nameservers"`
|
||||
}
|
||||
|
||||
// PatchMinimum defines model for PatchMinimum.
|
||||
type PatchMinimum struct {
|
||||
// Patch operation type
|
||||
// Op Patch operation type
|
||||
Op PatchMinimumOp `json:"op"`
|
||||
|
||||
// Values to be applied
|
||||
// Value Values to be applied
|
||||
Value []string `json:"value"`
|
||||
}
|
||||
|
||||
// Patch operation type
|
||||
// PatchMinimumOp Patch operation type
|
||||
type PatchMinimumOp string
|
||||
|
||||
// Peer defines model for Peer.
|
||||
type Peer struct {
|
||||
// Peer to Management connection status
|
||||
// Connected Peer to Management connection status
|
||||
Connected bool `json:"connected"`
|
||||
|
||||
// Groups that the peer belongs to
|
||||
// Groups Groups that the peer belongs to
|
||||
Groups []GroupMinimum `json:"groups"`
|
||||
|
||||
// Hostname of the machine
|
||||
// Hostname Hostname of the machine
|
||||
Hostname string `json:"hostname"`
|
||||
|
||||
// Peer ID
|
||||
// Id Peer ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// Peer's IP address
|
||||
// Ip Peer's IP address
|
||||
Ip string `json:"ip"`
|
||||
|
||||
// Last time peer connected to Netbird's management service
|
||||
// LastSeen Last time peer connected to Netbird's management service
|
||||
LastSeen time.Time `json:"last_seen"`
|
||||
|
||||
// Peer's hostname
|
||||
// Name Peer's hostname
|
||||
Name string `json:"name"`
|
||||
|
||||
// Peer's operating system and version
|
||||
// Os Peer's operating system and version
|
||||
Os string `json:"os"`
|
||||
|
||||
// Indicates whether SSH server is enabled on this peer
|
||||
// SshEnabled Indicates whether SSH server is enabled on this peer
|
||||
SshEnabled bool `json:"ssh_enabled"`
|
||||
|
||||
// Peer's desktop UI version
|
||||
// UiVersion Peer's desktop UI version
|
||||
UiVersion *string `json:"ui_version,omitempty"`
|
||||
|
||||
// User ID of the user that enrolled this peer
|
||||
// UserId User ID of the user that enrolled this peer
|
||||
UserId *string `json:"user_id,omitempty"`
|
||||
|
||||
// Peer's daemon or cli version
|
||||
// Version Peer's daemon or cli version
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// PeerMinimum defines model for PeerMinimum.
|
||||
type PeerMinimum struct {
|
||||
// Peer ID
|
||||
// Id Peer ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// Peer's hostname
|
||||
// Name Peer's hostname
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Route defines model for Route.
|
||||
type Route struct {
|
||||
// Route description
|
||||
// Description Route description
|
||||
Description string `json:"description"`
|
||||
|
||||
// Route status
|
||||
// Enabled Route status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Route Id
|
||||
// Id Route Id
|
||||
Id string `json:"id"`
|
||||
|
||||
// Indicate if peer should masquerade traffic to this route's prefix
|
||||
// Masquerade Indicate if peer should masquerade traffic to this route's prefix
|
||||
Masquerade bool `json:"masquerade"`
|
||||
|
||||
// Route metric number. Lowest number has higher priority
|
||||
// Metric Route metric number. Lowest number has higher priority
|
||||
Metric int `json:"metric"`
|
||||
|
||||
// Network range in CIDR format
|
||||
// Network Network range in CIDR format
|
||||
Network string `json:"network"`
|
||||
|
||||
// Route network identifier, to group HA routes
|
||||
// NetworkId Route network identifier, to group HA routes
|
||||
NetworkId string `json:"network_id"`
|
||||
|
||||
// Network type indicating if it is IPv4 or IPv6
|
||||
// NetworkType Network type indicating if it is IPv4 or IPv6
|
||||
NetworkType string `json:"network_type"`
|
||||
|
||||
// Peer Identifier associated with route
|
||||
// Peer Peer Identifier associated with route
|
||||
Peer string `json:"peer"`
|
||||
}
|
||||
|
||||
// RoutePatchOperation defines model for RoutePatchOperation.
|
||||
type RoutePatchOperation struct {
|
||||
// Patch operation type
|
||||
// Op Patch operation type
|
||||
Op RoutePatchOperationOp `json:"op"`
|
||||
|
||||
// Route field to update in form /<field>
|
||||
// Path Route field to update in form /<field>
|
||||
Path RoutePatchOperationPath `json:"path"`
|
||||
|
||||
// Values to be applied
|
||||
// Value Values to be applied
|
||||
Value []string `json:"value"`
|
||||
}
|
||||
|
||||
// Patch operation type
|
||||
// RoutePatchOperationOp Patch operation type
|
||||
type RoutePatchOperationOp string
|
||||
|
||||
// Route field to update in form /<field>
|
||||
// RoutePatchOperationPath Route field to update in form /<field>
|
||||
type RoutePatchOperationPath string
|
||||
|
||||
// RouteRequest defines model for RouteRequest.
|
||||
type RouteRequest struct {
|
||||
// Route description
|
||||
// Description Route description
|
||||
Description string `json:"description"`
|
||||
|
||||
// Route status
|
||||
// Enabled Route status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Indicate if peer should masquerade traffic to this route's prefix
|
||||
// Masquerade Indicate if peer should masquerade traffic to this route's prefix
|
||||
Masquerade bool `json:"masquerade"`
|
||||
|
||||
// Route metric number. Lowest number has higher priority
|
||||
// Metric Route metric number. Lowest number has higher priority
|
||||
Metric int `json:"metric"`
|
||||
|
||||
// Network range in CIDR format
|
||||
// Network Network range in CIDR format
|
||||
Network string `json:"network"`
|
||||
|
||||
// Route network identifier, to group HA routes
|
||||
// NetworkId Route network identifier, to group HA routes
|
||||
NetworkId string `json:"network_id"`
|
||||
|
||||
// Peer Identifier associated with route
|
||||
// Peer Peer Identifier associated with route
|
||||
Peer string `json:"peer"`
|
||||
}
|
||||
|
||||
// Rule defines model for Rule.
|
||||
type Rule struct {
|
||||
// Rule friendly description
|
||||
// Description Rule friendly description
|
||||
Description string `json:"description"`
|
||||
|
||||
// Rule destination groups
|
||||
// Destinations Rule destination groups
|
||||
Destinations []GroupMinimum `json:"destinations"`
|
||||
|
||||
// Rules status
|
||||
// Disabled Rules status
|
||||
Disabled bool `json:"disabled"`
|
||||
|
||||
// Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
||||
// Flow Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
||||
Flow string `json:"flow"`
|
||||
|
||||
// Rule ID
|
||||
// Id Rule ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// Rule name identifier
|
||||
// Name Rule name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// Rule source groups
|
||||
// Sources Rule source groups
|
||||
Sources []GroupMinimum `json:"sources"`
|
||||
}
|
||||
|
||||
// RuleMinimum defines model for RuleMinimum.
|
||||
type RuleMinimum struct {
|
||||
// Rule friendly description
|
||||
// Description Rule friendly description
|
||||
Description string `json:"description"`
|
||||
|
||||
// Rules status
|
||||
// Disabled Rules status
|
||||
Disabled bool `json:"disabled"`
|
||||
|
||||
// Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
||||
// Flow Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
||||
Flow string `json:"flow"`
|
||||
|
||||
// Rule name identifier
|
||||
// Name Rule name identifier
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// RulePatchOperation defines model for RulePatchOperation.
|
||||
type RulePatchOperation struct {
|
||||
// Patch operation type
|
||||
// Op Patch operation type
|
||||
Op RulePatchOperationOp `json:"op"`
|
||||
|
||||
// Rule field to update in form /<field>
|
||||
// Path Rule field to update in form /<field>
|
||||
Path RulePatchOperationPath `json:"path"`
|
||||
|
||||
// Values to be applied
|
||||
// Value Values to be applied
|
||||
Value []string `json:"value"`
|
||||
}
|
||||
|
||||
// Patch operation type
|
||||
// RulePatchOperationOp Patch operation type
|
||||
type RulePatchOperationOp string
|
||||
|
||||
// Rule field to update in form /<field>
|
||||
// RulePatchOperationPath Rule field to update in form /<field>
|
||||
type RulePatchOperationPath string
|
||||
|
||||
// SetupKey defines model for SetupKey.
|
||||
type SetupKey struct {
|
||||
// Setup key groups to auto-assign to peers registered with this key
|
||||
// AutoGroups Setup key groups to auto-assign to peers registered with this key
|
||||
AutoGroups []string `json:"auto_groups"`
|
||||
|
||||
// Setup Key expiration date
|
||||
// Expires Setup Key expiration date
|
||||
Expires time.Time `json:"expires"`
|
||||
|
||||
// Setup Key ID
|
||||
// Id Setup Key ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// Setup Key value
|
||||
// Key Setup Key value
|
||||
Key string `json:"key"`
|
||||
|
||||
// Setup key last usage date
|
||||
// LastUsed Setup key last usage date
|
||||
LastUsed time.Time `json:"last_used"`
|
||||
|
||||
// Setup key name identifier
|
||||
// Name Setup key name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// Setup key revocation status
|
||||
// Revoked Setup key revocation status
|
||||
Revoked bool `json:"revoked"`
|
||||
|
||||
// Setup key status, "valid", "overused","expired" or "revoked"
|
||||
// State Setup key status, "valid", "overused","expired" or "revoked"
|
||||
State string `json:"state"`
|
||||
|
||||
// Setup key type, one-off for single time usage and reusable
|
||||
// Type Setup key type, one-off for single time usage and reusable
|
||||
Type string `json:"type"`
|
||||
|
||||
// Setup key last update date
|
||||
// UpdatedAt Setup key last update date
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// Usage count of setup key
|
||||
// UsedTimes Usage count of setup key
|
||||
UsedTimes int `json:"used_times"`
|
||||
|
||||
// Setup key validity status
|
||||
// Valid Setup key validity status
|
||||
Valid bool `json:"valid"`
|
||||
}
|
||||
|
||||
// SetupKeyRequest defines model for SetupKeyRequest.
|
||||
type SetupKeyRequest struct {
|
||||
// Setup key groups to auto-assign to peers registered with this key
|
||||
// AutoGroups Setup key groups to auto-assign to peers registered with this key
|
||||
AutoGroups []string `json:"auto_groups"`
|
||||
|
||||
// Expiration time in seconds
|
||||
// ExpiresIn Expiration time in seconds
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
|
||||
// Setup Key name
|
||||
// Name Setup Key name
|
||||
Name string `json:"name"`
|
||||
|
||||
// Setup key revocation status
|
||||
// Revoked Setup key revocation status
|
||||
Revoked bool `json:"revoked"`
|
||||
|
||||
// Setup key type, one-off for single time usage and reusable
|
||||
// Type Setup key type, one-off for single time usage and reusable
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// User defines model for User.
|
||||
type User struct {
|
||||
// Groups to auto-assign to peers registered by this user
|
||||
// AutoGroups Groups to auto-assign to peers registered by this user
|
||||
AutoGroups []string `json:"auto_groups"`
|
||||
|
||||
// User's email address
|
||||
// Email User's email address
|
||||
Email string `json:"email"`
|
||||
|
||||
// User ID
|
||||
// Id User ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// User's name from idp provider
|
||||
// Name User's name from idp provider
|
||||
Name string `json:"name"`
|
||||
|
||||
// User's NetBird account role
|
||||
// Role User's NetBird account role
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
// UserRequest defines model for UserRequest.
|
||||
type UserRequest struct {
|
||||
// Groups to auto-assign to peers registered by this user
|
||||
// AutoGroups Groups to auto-assign to peers registered by this user
|
||||
AutoGroups []string `json:"auto_groups"`
|
||||
|
||||
// User's NetBird account role
|
||||
// Role User's NetBird account role
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
// PatchApiDnsNameserversIdJSONBody defines parameters for PatchApiDnsNameserversId.
|
||||
type PatchApiDnsNameserversIdJSONBody = []NameserverGroupPatchOperation
|
||||
|
||||
// PostApiGroupsJSONBody defines parameters for PostApiGroups.
|
||||
type PostApiGroupsJSONBody struct {
|
||||
Name string `json:"name"`
|
||||
@ -405,28 +501,22 @@ type PutApiPeersIdJSONBody struct {
|
||||
SshEnabled bool `json:"ssh_enabled"`
|
||||
}
|
||||
|
||||
// PostApiRoutesJSONBody defines parameters for PostApiRoutes.
|
||||
type PostApiRoutesJSONBody = RouteRequest
|
||||
|
||||
// PatchApiRoutesIdJSONBody defines parameters for PatchApiRoutesId.
|
||||
type PatchApiRoutesIdJSONBody = []RoutePatchOperation
|
||||
|
||||
// PutApiRoutesIdJSONBody defines parameters for PutApiRoutesId.
|
||||
type PutApiRoutesIdJSONBody = RouteRequest
|
||||
|
||||
// PostApiRulesJSONBody defines parameters for PostApiRules.
|
||||
type PostApiRulesJSONBody struct {
|
||||
// Rule friendly description
|
||||
// Description Rule friendly description
|
||||
Description string `json:"description"`
|
||||
Destinations *[]string `json:"destinations,omitempty"`
|
||||
|
||||
// Rules status
|
||||
// Disabled Rules status
|
||||
Disabled bool `json:"disabled"`
|
||||
|
||||
// Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
||||
// Flow Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
||||
Flow string `json:"flow"`
|
||||
|
||||
// Rule name identifier
|
||||
// Name Rule name identifier
|
||||
Name string `json:"name"`
|
||||
Sources *[]string `json:"sources,omitempty"`
|
||||
}
|
||||
@ -436,29 +526,29 @@ type PatchApiRulesIdJSONBody = []RulePatchOperation
|
||||
|
||||
// PutApiRulesIdJSONBody defines parameters for PutApiRulesId.
|
||||
type PutApiRulesIdJSONBody struct {
|
||||
// Rule friendly description
|
||||
// Description Rule friendly description
|
||||
Description string `json:"description"`
|
||||
Destinations *[]string `json:"destinations,omitempty"`
|
||||
|
||||
// Rules status
|
||||
// Disabled Rules status
|
||||
Disabled bool `json:"disabled"`
|
||||
|
||||
// Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
||||
// Flow Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
||||
Flow string `json:"flow"`
|
||||
|
||||
// Rule name identifier
|
||||
// Name Rule name identifier
|
||||
Name string `json:"name"`
|
||||
Sources *[]string `json:"sources,omitempty"`
|
||||
}
|
||||
|
||||
// PostApiSetupKeysJSONBody defines parameters for PostApiSetupKeys.
|
||||
type PostApiSetupKeysJSONBody = SetupKeyRequest
|
||||
// PostApiDnsNameserversJSONRequestBody defines body for PostApiDnsNameservers for application/json ContentType.
|
||||
type PostApiDnsNameserversJSONRequestBody = NameserverGroupRequest
|
||||
|
||||
// PutApiSetupKeysIdJSONBody defines parameters for PutApiSetupKeysId.
|
||||
type PutApiSetupKeysIdJSONBody = SetupKeyRequest
|
||||
// PatchApiDnsNameserversIdJSONRequestBody defines body for PatchApiDnsNameserversId for application/json ContentType.
|
||||
type PatchApiDnsNameserversIdJSONRequestBody = PatchApiDnsNameserversIdJSONBody
|
||||
|
||||
// PutApiUsersIdJSONBody defines parameters for PutApiUsersId.
|
||||
type PutApiUsersIdJSONBody = UserRequest
|
||||
// PutApiDnsNameserversIdJSONRequestBody defines body for PutApiDnsNameserversId for application/json ContentType.
|
||||
type PutApiDnsNameserversIdJSONRequestBody = NameserverGroupRequest
|
||||
|
||||
// PostApiGroupsJSONRequestBody defines body for PostApiGroups for application/json ContentType.
|
||||
type PostApiGroupsJSONRequestBody PostApiGroupsJSONBody
|
||||
@ -473,13 +563,13 @@ type PutApiGroupsIdJSONRequestBody PutApiGroupsIdJSONBody
|
||||
type PutApiPeersIdJSONRequestBody PutApiPeersIdJSONBody
|
||||
|
||||
// PostApiRoutesJSONRequestBody defines body for PostApiRoutes for application/json ContentType.
|
||||
type PostApiRoutesJSONRequestBody = PostApiRoutesJSONBody
|
||||
type PostApiRoutesJSONRequestBody = RouteRequest
|
||||
|
||||
// PatchApiRoutesIdJSONRequestBody defines body for PatchApiRoutesId for application/json ContentType.
|
||||
type PatchApiRoutesIdJSONRequestBody = PatchApiRoutesIdJSONBody
|
||||
|
||||
// PutApiRoutesIdJSONRequestBody defines body for PutApiRoutesId for application/json ContentType.
|
||||
type PutApiRoutesIdJSONRequestBody = PutApiRoutesIdJSONBody
|
||||
type PutApiRoutesIdJSONRequestBody = RouteRequest
|
||||
|
||||
// PostApiRulesJSONRequestBody defines body for PostApiRules for application/json ContentType.
|
||||
type PostApiRulesJSONRequestBody PostApiRulesJSONBody
|
||||
@ -491,10 +581,10 @@ type PatchApiRulesIdJSONRequestBody = PatchApiRulesIdJSONBody
|
||||
type PutApiRulesIdJSONRequestBody PutApiRulesIdJSONBody
|
||||
|
||||
// PostApiSetupKeysJSONRequestBody defines body for PostApiSetupKeys for application/json ContentType.
|
||||
type PostApiSetupKeysJSONRequestBody = PostApiSetupKeysJSONBody
|
||||
type PostApiSetupKeysJSONRequestBody = SetupKeyRequest
|
||||
|
||||
// PutApiSetupKeysIdJSONRequestBody defines body for PutApiSetupKeysId for application/json ContentType.
|
||||
type PutApiSetupKeysIdJSONRequestBody = PutApiSetupKeysIdJSONBody
|
||||
type PutApiSetupKeysIdJSONRequestBody = SetupKeyRequest
|
||||
|
||||
// PutApiUsersIdJSONRequestBody defines body for PutApiUsersId for application/json ContentType.
|
||||
type PutApiUsersIdJSONRequestBody = PutApiUsersIdJSONBody
|
||||
type PutApiUsersIdJSONRequestBody = UserRequest
|
||||
|
@ -34,6 +34,7 @@ func APIHandler(accountManager s.AccountManager, authIssuer string, authAudience
|
||||
keysHandler := NewSetupKeysHandler(accountManager, authAudience)
|
||||
userHandler := NewUserHandler(accountManager, authAudience)
|
||||
routesHandler := NewRoutes(accountManager, authAudience)
|
||||
nameserversHandler := NewNameservers(accountManager, authAudience)
|
||||
|
||||
apiHandler.HandleFunc("/api/peers", peersHandler.GetPeers).Methods("GET", "OPTIONS")
|
||||
apiHandler.HandleFunc("/api/peers/{id}", peersHandler.HandlePeer).
|
||||
@ -67,6 +68,13 @@ func APIHandler(accountManager s.AccountManager, authIssuer string, authAudience
|
||||
apiHandler.HandleFunc("/api/routes/{id}", routesHandler.GetRouteHandler).Methods("GET", "OPTIONS")
|
||||
apiHandler.HandleFunc("/api/routes/{id}", routesHandler.DeleteRouteHandler).Methods("DELETE", "OPTIONS")
|
||||
|
||||
apiHandler.HandleFunc("/api/dns/nameservers", nameserversHandler.GetAllNameserversHandler).Methods("GET", "OPTIONS")
|
||||
apiHandler.HandleFunc("/api/dns/nameservers", nameserversHandler.CreateNameserverGroupHandler).Methods("POST", "OPTIONS")
|
||||
apiHandler.HandleFunc("/api/dns/nameservers/{id}", nameserversHandler.UpdateNameserverGroupHandler).Methods("PUT", "OPTIONS")
|
||||
apiHandler.HandleFunc("/api/dns/nameservers/{id}", nameserversHandler.PatchNameserverGroupHandler).Methods("PATCH", "OPTIONS")
|
||||
apiHandler.HandleFunc("/api/dns/nameservers/{id}", nameserversHandler.GetNameserverGroupHandler).Methods("GET", "OPTIONS")
|
||||
apiHandler.HandleFunc("/api/dns/nameservers/{id}", nameserversHandler.DeleteNameserverGroupHandler).Methods("DELETE", "OPTIONS")
|
||||
|
||||
return apiHandler, nil
|
||||
|
||||
}
|
||||
|
286
management/server/http/nameservers.go
Normal file
286
management/server/http/nameservers.go
Normal file
@ -0,0 +1,286 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Nameservers is the nameserver group handler of the account
|
||||
type Nameservers struct {
|
||||
jwtExtractor jwtclaims.ClaimsExtractor
|
||||
accountManager server.AccountManager
|
||||
authAudience string
|
||||
}
|
||||
|
||||
// NewNameservers returns a new instance of Nameservers handler
|
||||
func NewNameservers(accountManager server.AccountManager, authAudience string) *Nameservers {
|
||||
return &Nameservers{
|
||||
accountManager: accountManager,
|
||||
authAudience: authAudience,
|
||||
jwtExtractor: *jwtclaims.NewClaimsExtractor(nil),
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllNameserversHandler returns the list of nameserver groups for the account
|
||||
func (h *Nameservers) GetAllNameserversHandler(w http.ResponseWriter, r *http.Request) {
|
||||
account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
nsGroups, err := h.accountManager.ListNameServerGroups(account.Id)
|
||||
if err != nil {
|
||||
toHTTPError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
apiNameservers := make([]*api.NameserverGroup, 0)
|
||||
for _, r := range nsGroups {
|
||||
apiNameservers = append(apiNameservers, toNameserverGroupResponse(r))
|
||||
}
|
||||
|
||||
writeJSONObject(w, apiNameservers)
|
||||
}
|
||||
|
||||
// CreateNameserverGroupHandler handles nameserver group creation request
|
||||
func (h *Nameservers) CreateNameserverGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
var req api.PostApiDnsNameserversJSONRequestBody
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
nsList, err := toServerNSList(req.Nameservers)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
nsGroup, err := h.accountManager.CreateNameServerGroup(account.Id, req.Name, req.Description, nsList, req.Groups, req.Enabled)
|
||||
if err != nil {
|
||||
toHTTPError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
resp := toNameserverGroupResponse(nsGroup)
|
||||
|
||||
writeJSONObject(w, &resp)
|
||||
}
|
||||
|
||||
// UpdateNameserverGroupHandler handles update to a nameserver group identified by a given ID
|
||||
func (h *Nameservers) UpdateNameserverGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
nsGroupID := mux.Vars(r)["id"]
|
||||
if len(nsGroupID) == 0 {
|
||||
http.Error(w, "invalid nameserver group ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req api.PutApiDnsNameserversIdJSONRequestBody
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
nsList, err := toServerNSList(req.Nameservers)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
updatedNSGroup := &nbdns.NameServerGroup{
|
||||
ID: nsGroupID,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
NameServers: nsList,
|
||||
Groups: req.Groups,
|
||||
Enabled: req.Enabled,
|
||||
}
|
||||
|
||||
err = h.accountManager.SaveNameServerGroup(account.Id, updatedNSGroup)
|
||||
if err != nil {
|
||||
toHTTPError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
resp := toNameserverGroupResponse(updatedNSGroup)
|
||||
|
||||
writeJSONObject(w, &resp)
|
||||
}
|
||||
|
||||
// PatchNameserverGroupHandler handles patch updates to a nameserver group identified by a given ID
|
||||
func (h *Nameservers) PatchNameserverGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
nsGroupID := mux.Vars(r)["id"]
|
||||
if len(nsGroupID) == 0 {
|
||||
http.Error(w, "invalid nameserver group ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req api.PatchApiDnsNameserversIdJSONRequestBody
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var operations []server.NameServerGroupUpdateOperation
|
||||
for _, patch := range req {
|
||||
if patch.Op != api.NameserverGroupPatchOperationOpReplace {
|
||||
http.Error(w, fmt.Sprintf("nameserver groups only accepts replace operations, got %s", patch.Op),
|
||||
http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
switch patch.Path {
|
||||
case api.NameserverGroupPatchOperationPathName:
|
||||
operations = append(operations, server.NameServerGroupUpdateOperation{
|
||||
Type: server.UpdateNameServerGroupName,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.NameserverGroupPatchOperationPathDescription:
|
||||
operations = append(operations, server.NameServerGroupUpdateOperation{
|
||||
Type: server.UpdateNameServerGroupDescription,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.NameserverGroupPatchOperationPathNameservers:
|
||||
operations = append(operations, server.NameServerGroupUpdateOperation{
|
||||
Type: server.UpdateNameServerGroupNameServers,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.NameserverGroupPatchOperationPathGroups:
|
||||
operations = append(operations, server.NameServerGroupUpdateOperation{
|
||||
Type: server.UpdateNameServerGroupGroups,
|
||||
Values: patch.Value,
|
||||
})
|
||||
case api.NameserverGroupPatchOperationPathEnabled:
|
||||
operations = append(operations, server.NameServerGroupUpdateOperation{
|
||||
Type: server.UpdateNameServerGroupEnabled,
|
||||
Values: patch.Value,
|
||||
})
|
||||
default:
|
||||
http.Error(w, "invalid patch path", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
updatedNSGroup, err := h.accountManager.UpdateNameServerGroup(account.Id, nsGroupID, operations)
|
||||
if err != nil {
|
||||
toHTTPError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
resp := toNameserverGroupResponse(updatedNSGroup)
|
||||
|
||||
writeJSONObject(w, &resp)
|
||||
}
|
||||
|
||||
// DeleteNameserverGroupHandler handles nameserver group deletion request
|
||||
func (h *Nameservers) DeleteNameserverGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
nsGroupID := mux.Vars(r)["id"]
|
||||
if len(nsGroupID) == 0 {
|
||||
http.Error(w, "invalid nameserver group ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.accountManager.DeleteNameServerGroup(account.Id, nsGroupID)
|
||||
if err != nil {
|
||||
toHTTPError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSONObject(w, "")
|
||||
}
|
||||
|
||||
// GetNameserverGroupHandler handles a nameserver group Get request identified by ID
|
||||
func (h *Nameservers) GetNameserverGroupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
account, err := getJWTAccount(h.accountManager, h.jwtExtractor, h.authAudience, r)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
nsGroupID := mux.Vars(r)["id"]
|
||||
if len(nsGroupID) == 0 {
|
||||
http.Error(w, "invalid nameserver group ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
nsGroup, err := h.accountManager.GetNameServerGroup(account.Id, nsGroupID)
|
||||
if err != nil {
|
||||
toHTTPError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
resp := toNameserverGroupResponse(nsGroup)
|
||||
|
||||
writeJSONObject(w, &resp)
|
||||
|
||||
}
|
||||
|
||||
func toServerNSList(apiNSList []api.Nameserver) ([]nbdns.NameServer, error) {
|
||||
var nsList []nbdns.NameServer
|
||||
for _, apiNS := range apiNSList {
|
||||
parsed, err := nbdns.ParseNameServerURL(fmt.Sprintf("%s://%s:%d", apiNS.NsType, apiNS.Ip, apiNS.Port))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nsList = append(nsList, parsed)
|
||||
}
|
||||
|
||||
return nsList, nil
|
||||
}
|
||||
|
||||
func toNameserverGroupResponse(serverNSGroup *nbdns.NameServerGroup) *api.NameserverGroup {
|
||||
var nsList []api.Nameserver
|
||||
for _, ns := range serverNSGroup.NameServers {
|
||||
apiNS := api.Nameserver{
|
||||
Ip: ns.IP.String(),
|
||||
NsType: api.NameserverNsType(ns.NSType.String()),
|
||||
Port: ns.Port,
|
||||
}
|
||||
nsList = append(nsList, apiNS)
|
||||
}
|
||||
|
||||
return &api.NameserverGroup{
|
||||
Id: serverNSGroup.ID,
|
||||
Name: serverNSGroup.Name,
|
||||
Description: serverNSGroup.Description,
|
||||
Groups: serverNSGroup.Groups,
|
||||
Nameservers: nsList,
|
||||
Enabled: serverNSGroup.Enabled,
|
||||
}
|
||||
}
|
287
management/server/http/nameservers_test.go
Normal file
287
management/server/http/nameservers_test.go
Normal file
@ -0,0 +1,287 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
)
|
||||
|
||||
const (
|
||||
existingNSGroupID = "existingNSGroupID"
|
||||
notFoundNSGroupID = "notFoundNSGroupID"
|
||||
testNSGroupAccountID = "test_id"
|
||||
)
|
||||
|
||||
var testingNSAccount = &server.Account{
|
||||
Id: testNSGroupAccountID,
|
||||
Domain: "hotmail.com",
|
||||
}
|
||||
|
||||
var baseExistingNSGroup = &nbdns.NameServerGroup{
|
||||
ID: existingNSGroupID,
|
||||
Name: "super",
|
||||
Description: "super",
|
||||
NameServers: []nbdns.NameServer{
|
||||
{
|
||||
IP: netip.MustParseAddr("1.1.1.1"),
|
||||
NSType: nbdns.UDPNameServerType,
|
||||
Port: nbdns.DefaultDNSPort,
|
||||
},
|
||||
{
|
||||
IP: netip.MustParseAddr("1.1.2.2"),
|
||||
NSType: nbdns.UDPNameServerType,
|
||||
Port: nbdns.DefaultDNSPort,
|
||||
},
|
||||
},
|
||||
Groups: []string{"testing"},
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
func initNameserversTestData() *Nameservers {
|
||||
return &Nameservers{
|
||||
accountManager: &mock_server.MockAccountManager{
|
||||
GetNameServerGroupFunc: func(accountID, nsGroupID string) (*nbdns.NameServerGroup, error) {
|
||||
if nsGroupID == existingNSGroupID {
|
||||
return baseExistingNSGroup.Copy(), nil
|
||||
}
|
||||
return nil, status.Errorf(codes.NotFound, "nameserver group with ID %s not found", nsGroupID)
|
||||
},
|
||||
CreateNameServerGroupFunc: func(accountID string, name, description string, nameServerList []nbdns.NameServer, groups []string, enabled bool) (*nbdns.NameServerGroup, error) {
|
||||
return &nbdns.NameServerGroup{
|
||||
ID: existingNSGroupID,
|
||||
Name: name,
|
||||
Description: description,
|
||||
NameServers: nameServerList,
|
||||
Groups: groups,
|
||||
Enabled: enabled,
|
||||
}, nil
|
||||
},
|
||||
DeleteNameServerGroupFunc: func(accountID, nsGroupID string) error {
|
||||
return nil
|
||||
},
|
||||
SaveNameServerGroupFunc: func(accountID string, nsGroupToSave *nbdns.NameServerGroup) error {
|
||||
if nsGroupToSave.ID == existingNSGroupID {
|
||||
return nil
|
||||
}
|
||||
return status.Errorf(codes.NotFound, "nameserver group with ID %s was not found", nsGroupToSave.ID)
|
||||
},
|
||||
UpdateNameServerGroupFunc: func(accountID, nsGroupID string, operations []server.NameServerGroupUpdateOperation) (*nbdns.NameServerGroup, error) {
|
||||
nsGroupToUpdate := baseExistingNSGroup.Copy()
|
||||
if nsGroupID != nsGroupToUpdate.ID {
|
||||
return nil, status.Errorf(codes.NotFound, "nameserver group ID %s no longer exists", nsGroupID)
|
||||
}
|
||||
for _, operation := range operations {
|
||||
switch operation.Type {
|
||||
case server.UpdateNameServerGroupName:
|
||||
nsGroupToUpdate.Name = operation.Values[0]
|
||||
case server.UpdateNameServerGroupDescription:
|
||||
nsGroupToUpdate.Description = operation.Values[0]
|
||||
case server.UpdateNameServerGroupNameServers:
|
||||
var parsedNSList []nbdns.NameServer
|
||||
for _, nsURL := range operation.Values {
|
||||
parsed, err := nbdns.ParseNameServerURL(nsURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsedNSList = append(parsedNSList, parsed)
|
||||
}
|
||||
nsGroupToUpdate.NameServers = parsedNSList
|
||||
}
|
||||
}
|
||||
return nsGroupToUpdate, nil
|
||||
},
|
||||
GetAccountWithAuthorizationClaimsFunc: func(_ jwtclaims.AuthorizationClaims) (*server.Account, error) {
|
||||
return testingNSAccount, nil
|
||||
},
|
||||
},
|
||||
authAudience: "",
|
||||
jwtExtractor: jwtclaims.ClaimsExtractor{
|
||||
ExtractClaimsFromRequestContext: func(r *http.Request, authAudiance string) jwtclaims.AuthorizationClaims {
|
||||
return jwtclaims.AuthorizationClaims{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: testNSGroupAccountID,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestNameserversHandlers(t *testing.T) {
|
||||
tt := []struct {
|
||||
name string
|
||||
expectedStatus int
|
||||
expectedBody bool
|
||||
expectedNSGroup *api.NameserverGroup
|
||||
requestType string
|
||||
requestPath string
|
||||
requestBody io.Reader
|
||||
}{
|
||||
{
|
||||
name: "Get Existing Nameserver Group",
|
||||
requestType: http.MethodGet,
|
||||
requestPath: "/api/dns/nameservers/" + existingNSGroupID,
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedNSGroup: toNameserverGroupResponse(baseExistingNSGroup),
|
||||
},
|
||||
{
|
||||
name: "Get Not Existing Nameserver Group",
|
||||
requestType: http.MethodGet,
|
||||
requestPath: "/api/dns/nameservers/" + notFoundNSGroupID,
|
||||
expectedStatus: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
name: "POST OK",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/dns/nameservers",
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte("{\"name\":\"name\",\"Description\":\"Post\",\"nameservers\":[{\"ip\":\"1.1.1.1\",\"ns_type\":\"udp\",\"port\":53}],\"groups\":[\"group\"],\"enabled\":true}")),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedNSGroup: &api.NameserverGroup{
|
||||
Id: existingNSGroupID,
|
||||
Name: "name",
|
||||
Description: "Post",
|
||||
Nameservers: []api.Nameserver{
|
||||
{
|
||||
Ip: "1.1.1.1",
|
||||
NsType: "udp",
|
||||
Port: 53,
|
||||
},
|
||||
},
|
||||
Groups: []string{"group"},
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "POST Invalid Nameserver",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/dns/nameservers",
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte("{\"name\":\"name\",\"Description\":\"Post\",\"nameservers\":[{\"ip\":\"1000\",\"ns_type\":\"udp\",\"port\":53}],\"groups\":[\"group\"],\"enabled\":true}")),
|
||||
expectedStatus: http.StatusBadRequest,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
name: "PUT OK",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/dns/nameservers/" + existingNSGroupID,
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte("{\"name\":\"name\",\"Description\":\"Post\",\"nameservers\":[{\"ip\":\"1.1.1.1\",\"ns_type\":\"udp\",\"port\":53}],\"groups\":[\"group\"],\"enabled\":true}")),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedNSGroup: &api.NameserverGroup{
|
||||
Id: existingNSGroupID,
|
||||
Name: "name",
|
||||
Description: "Post",
|
||||
Nameservers: []api.Nameserver{
|
||||
{
|
||||
Ip: "1.1.1.1",
|
||||
NsType: "udp",
|
||||
Port: 53,
|
||||
},
|
||||
},
|
||||
Groups: []string{"group"},
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PUT Not Existing Nameserver Group",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/dns/nameservers/" + notFoundNSGroupID,
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte("{\"name\":\"name\",\"Description\":\"Post\",\"nameservers\":[{\"ip\":\"1.1.1.1\",\"ns_type\":\"udp\",\"port\":53}],\"groups\":[\"group\"],\"enabled\":true}")),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
name: "PUT Invalid Nameserver",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/dns/nameservers/" + notFoundNSGroupID,
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte("{\"name\":\"name\",\"Description\":\"Post\",\"nameservers\":[{\"ip\":\"100\",\"ns_type\":\"udp\",\"port\":53}],\"groups\":[\"group\"],\"enabled\":true}")),
|
||||
expectedStatus: http.StatusBadRequest,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
name: "PATCH OK",
|
||||
requestType: http.MethodPatch,
|
||||
requestPath: "/api/dns/nameservers/" + existingNSGroupID,
|
||||
requestBody: bytes.NewBufferString("[{\"op\":\"replace\",\"path\":\"description\",\"value\":[\"NewDesc\"]}]"),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedNSGroup: &api.NameserverGroup{
|
||||
Id: existingNSGroupID,
|
||||
Name: baseExistingNSGroup.Name,
|
||||
Description: "NewDesc",
|
||||
Nameservers: toNameserverGroupResponse(baseExistingNSGroup).Nameservers,
|
||||
Groups: baseExistingNSGroup.Groups,
|
||||
Enabled: baseExistingNSGroup.Enabled,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PATCH Invalid Nameserver Group OK",
|
||||
requestType: http.MethodPatch,
|
||||
requestPath: "/api/dns/nameservers/" + notFoundRouteID,
|
||||
requestBody: bytes.NewBufferString("[{\"op\":\"replace\",\"path\":\"description\",\"value\":[\"NewDesc\"]}]"),
|
||||
expectedStatus: http.StatusNotFound,
|
||||
expectedBody: false,
|
||||
},
|
||||
}
|
||||
|
||||
p := initNameserversTestData()
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/dns/nameservers/{id}", p.GetNameserverGroupHandler).Methods("GET")
|
||||
router.HandleFunc("/api/dns/nameservers", p.CreateNameserverGroupHandler).Methods("POST")
|
||||
router.HandleFunc("/api/dns/nameservers/{id}", p.DeleteNameserverGroupHandler).Methods("DELETE")
|
||||
router.HandleFunc("/api/dns/nameservers/{id}", p.UpdateNameserverGroupHandler).Methods("PUT")
|
||||
router.HandleFunc("/api/dns/nameservers/{id}", p.PatchNameserverGroupHandler).Methods("PATCH")
|
||||
router.ServeHTTP(recorder, req)
|
||||
|
||||
res := recorder.Result()
|
||||
defer res.Body.Close()
|
||||
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("I don't know what I expected; %v", err)
|
||||
}
|
||||
|
||||
if status := recorder.Code; status != tc.expectedStatus {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v, content: %s",
|
||||
status, tc.expectedStatus, string(content))
|
||||
return
|
||||
}
|
||||
|
||||
if !tc.expectedBody {
|
||||
return
|
||||
}
|
||||
|
||||
got := &api.NameserverGroup{}
|
||||
if err = json.Unmarshal(content, &got); err != nil {
|
||||
t.Fatalf("Sent content is not in correct json format; %v", err)
|
||||
}
|
||||
assert.Equal(t, tc.expectedNSGroup, got)
|
||||
})
|
||||
}
|
||||
}
|
@ -123,7 +123,7 @@ func (h *Routes) UpdateRouteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var req api.PutApiRoutesIdJSONBody
|
||||
var req api.PutApiRoutesIdJSONRequestBody
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
|
@ -6,11 +6,14 @@ import (
|
||||
"fmt"
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
//writeJSONObject simply writes object to the HTTP reponse in JSON format
|
||||
// writeJSONObject simply writes object to the HTTP reponse in JSON format
|
||||
func writeJSONObject(w http.ResponseWriter, obj interface{}) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
@ -21,7 +24,7 @@ func writeJSONObject(w http.ResponseWriter, obj interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
//Duration is used strictly for JSON requests/responses due to duration marshalling issues
|
||||
// Duration is used strictly for JSON requests/responses due to duration marshalling issues
|
||||
type Duration struct {
|
||||
time.Duration
|
||||
}
|
||||
@ -64,3 +67,25 @@ func getJWTAccount(accountManager server.AccountManager,
|
||||
|
||||
return account, nil
|
||||
}
|
||||
|
||||
func toHTTPError(err error, w http.ResponseWriter) {
|
||||
errStatus, ok := status.FromError(err)
|
||||
if ok && errStatus.Code() == codes.Internal {
|
||||
http.Error(w, errStatus.String(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if ok && errStatus.Code() == codes.NotFound {
|
||||
http.Error(w, errStatus.String(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if ok && errStatus.Code() == codes.InvalidArgument {
|
||||
http.Error(w, errStatus.String(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
unhandledMSG := fmt.Sprintf("got unhandled error code, error: %s", errStatus.String())
|
||||
log.Error(unhandledMSG)
|
||||
http.Error(w, unhandledMSG, http.StatusInternalServerError)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user