[management] switch to libopenapi for managing of openapi-based api (#8056)

* use libopenapi OpenAPI generator

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* added a handler for v1alpha1/peers

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* wire up request validator

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* wired up spec-based validation

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* use sync validation; set base url to v1alpha1

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* moved stuff around, extracted runtime libopenapu deps into runtime_tooling

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* testing /peers path params

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* fixed tests

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* added user schemas and paths

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* use api validation in tests

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* post-merge fixes

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* deleted tmp command used to test validator integration

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* require request body in post/put requests in order to force validation

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* making linter happy

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* switch to api/v1alpha1

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* go mod tidy

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* keep the original order of middleware: metrics, cors, then auth

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* return 422 on validation errors

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* cleanups

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* more cleanups

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* v1alpha1 spec cleanups

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* no need for a double-pointer

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* more linter fixes

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* removed more double pointers

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* use di to inject api_v0 and api_v1 http routers

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* do not re-add middleware on repeated call to ApiHandler

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

* calling ApiRouter() now also calls ApiV1Router()

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>

---------

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
This commit is contained in:
dmitri-netbird
2026-10-07 19:07:31 +02:00
committed by GitHub
parent 192d3d0344
commit 24cb7b75c2
25 changed files with 4509 additions and 64 deletions
@@ -0,0 +1,997 @@
openapi: 3.1.0
servers:
- url: /api/v1alpha1
description: Default server
info:
title: NetBird REST API
description: API to manipulate groups, rules, policies and retrieve information about peers and users
version: 1.0.0-alpha1
tags:
- name: Users
description: Interact with and view information about users.
- name: Tokens
description: Interact with and view information about tokens.
- name: Peers
description: Interact with and view information about peers.
- name: Setup Keys
description: Interact with and view information about setup keys.
- name: Groups
description: Interact with and view information about groups.
- name: Policies
description: Interact with and view information about policies.
- name: Posture Checks
description: Interact with and view information about posture checks.
- name: Routes
description: Interact with and view information about routes.
- name: DNS
description: Interact with and view information about DNS configuration.
- name: DNS Zones
description: Interact with and view information about custom DNS zones.
- name: Events
description: View information about the account and network events.
- name: Accounts
description: View information about the accounts.
- name: Ingress Ports
description: Interact with and view information about the ingress peers and ports.
x-cloud-only: true
- name: Identity Providers
description: Interact with and view information about identity providers.
- name: Services
description: Interact with and view information about reverse proxy services.
- name: Instance
description: Instance setup and status endpoints for initial configuration.
- name: Jobs
description: Interact with and view information about remote jobs.
x-experimental: true
- name: Usage
description: Retrieve current usage statistics for the account.
x-cloud-only: true
- name: Subscription
description: Manage and view information about account subscriptions.
x-cloud-only: true
- name: Plans
description: Retrieve available plans and products.
x-cloud-only: true
- name: Checkout
description: Manage checkout sessions for plan subscriptions.
x-cloud-only: true
- name: AWS Marketplace
description: Manage AWS Marketplace subscriptions.
x-cloud-only: true
- name: Portal
description: Access customer portal for subscription management.
x-cloud-only: true
- name: Invoice
description: Manage and retrieve account invoices.
x-cloud-only: true
- name: MSP
description: MSP portal for Tenant management.
x-cloud-only: true
- name: IDP SCIM Integrations
description: Manage generic SCIM identity provider integrations for user and group sync.
x-cloud-only: true
- name: IDP Google Integrations
description: Manage Google Workspace identity provider integrations for user and group sync.
x-cloud-only: true
- name: IDP Azure Integrations
description: Manage Azure AD identity provider integrations for user and group sync.
x-cloud-only: true
- name: IDP Okta SCIM Integrations
description: Manage Okta SCIM identity provider integrations for user and group sync.
x-cloud-only: true
- name: EDR Intune Integrations
description: Manage Microsoft Intune EDR integrations.
x-cloud-only: true
- name: EDR SentinelOne Integrations
description: Manage SentinelOne EDR integrations.
x-cloud-only: true
- name: EDR Falcon Integrations
description: Manage CrowdStrike Falcon EDR integrations.
x-cloud-only: true
- name: EDR Huntress Integrations
description: Manage Huntress EDR integrations.
x-cloud-only: true
- name: EDR FleetDM Integrations
description: Manage FleetDM EDR integrations.
x-cloud-only: true
- name: EDR Peers
description: Manage EDR compliance bypass for peers.
x-cloud-only: true
- name: Event Streaming Integrations
description: Manage event streaming integrations.
x-cloud-only: true
- name: Notifications
description: Manage notification channels for account event alerts.
x-cloud-only: true
components:
schemas:
CountryCode:
description: 2-letter ISO 3166-1 alpha-2 code that represents the country
type: string
example: "DE"
CityName:
description: Commonly used English name of the city
type: string
example: "Berlin"
Country:
description: Describe country geographical location information
type: object
properties:
country_name:
description: Commonly used English name of the country
type: string
example: "Germany"
country_code:
$ref: '#/components/schemas/CountryCode'
required:
- country_name
- country_code
City:
description: Describe city geographical location information
type: object
properties:
geoname_id:
description: Integer ID of the record in GeoNames database
type: integer
example: 2950158
city_name:
description: Commonly used English name of the city
type: string
example: "Berlin"
required:
- geoname_id
- city_name
ErrorResponse:
type: object
description: Standard error response
properties:
message:
type: string
description: A human-readable error message.
example: "couldn't parse JSON request"
PeerBatch:
allOf:
- $ref: '#/components/schemas/Peer'
- type: object
properties:
created_at:
description: Peer creation date (UTC)
type: string
format: date-time
example: "2023-05-05T09:00:35.477782Z"
accessible_peers_count:
description: Number of accessible peers
type: integer
example: 5
required:
- created_at
- accessible_peers_count
PeerMinimum:
type: object
properties:
id:
description: Peer ID
type: string
example: chacbco6lnnbn6cg5s90
name:
description: Peer's hostname
type: string
example: stage-host-1
required:
- id
- name
GroupMinimum:
type: object
properties:
id:
description: Group ID
type: string
example: ch8i4ug6lnn4g9hqv7m0
name:
description: Group Name identifier
type: string
example: devs
peers_count:
description: Count of peers associated to the group
type: integer
example: 2
resources_count:
description: Count of resources associated to the group
type: integer
example: 5
issued:
description: How the group was issued (api, integration, jwt)
type: string
enum:
- "api"
- "integration"
- "jwt"
example: api
required:
- id
- name
- peers_count
- resources_count
PeerLocalFlags:
type: object
properties:
rosenpass_enabled:
description: Indicates whether Rosenpass is enabled on this peer
type: boolean
example: true
rosenpass_permissive:
description: Indicates whether Rosenpass is in permissive mode or not
type: boolean
example: false
server_ssh_allowed:
description: Indicates whether SSH access this peer is allowed or not
type: boolean
example: true
remote_jobs_allowed:
description: Indicates whether the peer has opted into management-requested remote jobs (e.g. debug bundles)
type: boolean
example: true
disable_client_routes:
description: Indicates whether client routes are disabled on this peer or not
type: boolean
example: false
disable_server_routes:
description: Indicates whether server routes are disabled on this peer or not
type: boolean
example: false
disable_dns:
description: Indicates whether DNS management is disabled on this peer or not
type: boolean
example: false
disable_firewall:
description: Indicates whether firewall management is disabled on this peer or not
type: boolean
example: false
block_lan_access:
description: Indicates whether LAN access is blocked on this peer when used as a routing peer
type: boolean
example: false
block_inbound:
description: Indicates whether inbound traffic is blocked on this peer
type: boolean
example: false
lazy_connection_enabled:
description: Indicates whether lazy connection is enabled on this peer
type: boolean
example: false
Peer:
allOf:
- $ref: '#/components/schemas/PeerMinimum'
- type: object
properties:
created_at:
description: Peer creation date (UTC)
type: string
format: date-time
example: "2023-05-05T09:00:35.477782Z"
ip:
description: Peer's IP address
type: string
example: 10.64.0.1
ipv6:
description: Peer's IPv6 overlay address
type: string
format: ipv6
example: "fd00:4e42:ab12::1"
connection_ip:
description: Peer's public connection IP address
type: string
example: 35.64.0.1
connected:
description: Peer to Management connection status
type: boolean
example: true
last_seen:
description: Last time peer connected to Netbird's management service
type: string
format: date-time
example: "2023-05-05T10:05:26.420578Z"
os:
description: Peer's operating system and version
type: string
example: Darwin 13.2.1
kernel_version:
description: Peer's operating system kernel version
type: string
example: 23.2.0
geoname_id:
description: Unique identifier from the GeoNames database for a specific geographical location.
type: integer
example: 2643743
version:
description: Peer's daemon or cli version
type: string
example: 0.14.0
groups:
description: Groups that the peer belongs to
type: array
items:
$ref: '#/components/schemas/GroupMinimum'
ssh_enabled:
description: Indicates whether SSH server is enabled on this peer
type: boolean
example: true
user_id:
description: User ID of the user that enrolled this peer
type: string
example: google-oauth2|277474792786460067937
hostname:
description: Hostname of the machine
type: string
example: stage-host-1
ui_version:
description: Peer's desktop UI version
type: string
example: 0.14.0
dns_label:
description: Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
type: string
example: stage-host-1.netbird.cloud
login_expiration_enabled:
description: Indicates whether peer login expiration has been enabled or not
type: boolean
example: false
login_expired:
description: Indicates whether peer's login expired or not
type: boolean
example: false
last_login:
description: Last time this peer performed log in (authentication). E.g., user authenticated.
type: string
format: date-time
example: "2023-05-05T09:00:35.477782Z"
inactivity_expiration_enabled:
description: Indicates whether peer inactivity expiration has been enabled or not
type: boolean
example: false
approval_required:
description: (Cloud only) Indicates whether peer needs approval
type: boolean
example: true
disapproval_reason:
description: (Cloud only) Reason why the peer requires approval
type: string
country_code:
$ref: '#/components/schemas/CountryCode'
city_name:
$ref: '#/components/schemas/CityName'
serial_number:
description: System serial number
type: string
example: "C02XJ0J0JGH7"
extra_dns_labels:
description: Extra DNS labels added to the peer
type: array
items:
type: string
example: "stage-host-1"
ephemeral:
description: Indicates whether the peer is ephemeral or not
type: boolean
example: false
local_flags:
$ref: '#/components/schemas/PeerLocalFlags'
required:
- city_name
- connected
- connection_ip
- country_code
- created_at
- dns_label
- geoname_id
- groups
- hostname
- ip
- kernel_version
- last_login
- last_seen
- login_expiration_enabled
- login_expired
- inactivity_expiration_enabled
- os
- ssh_enabled
- user_id
- version
- ui_version
- approval_required
- serial_number
- extra_dns_labels
- ephemeral
PeerRequest:
type: object
properties:
name:
type: string
example: stage-host-1
ssh_enabled:
type: boolean
example: true
login_expiration_enabled:
type: boolean
example: false
inactivity_expiration_enabled:
type: boolean
example: false
approval_required:
description: (Cloud only) Indicates whether peer needs approval
type: boolean
example: true
ip:
description: Peer's IP address
type: string
format: ipv4
example: 100.64.0.15
ipv6:
description: Peer's IPv6 overlay address. Omitted if IPv6 is not enabled for the account.
type: string
format: ipv6
example: "fd00:4e42:ab12::1"
required:
- name
- ssh_enabled
- login_expiration_enabled
- inactivity_expiration_enabled
User:
type: object
properties:
id:
description: User ID
type: string
example: google-oauth2|277474792786460067937
email:
description: User's email address
type: string
example: demo@netbird.io
password:
description: User's password. Only present when user is created (create user endpoint is called) and only when IdP supports user creation with password.
type: string
example: super_secure_password
name:
description: User's name from idp provider
type: string
example: Tom Schulz
role:
description: User's NetBird account role
type: string
example: admin
status:
description: User's status
type: string
enum:
- "active"
- "invited"
- "blocked"
example: active
last_login:
description: Last time this user performed a login to the dashboard
type: string
format: date-time
example: "2023-05-05T09:00:35.477782Z"
auto_groups:
description: Group IDs to auto-assign to peers registered by this user
type: array
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
is_current:
description: Is true if authenticated user is the same as this user
type: boolean
readOnly: true
example: true
is_service_user:
description: Is true if this user is a service user
type: boolean
readOnly: true
example: false
is_blocked:
description: Is true if this user is blocked. Blocked users can't use the system
type: boolean
example: false
pending_approval:
description: Is true if this user requires approval before being activated. Only applicable for users joining via domain matching when user_approval_required is enabled.
type: boolean
example: false
issued:
description: How user was issued by API or Integration
type: string
example: api
idp_id:
description: Identity provider ID (connector ID) that the user authenticated with. Only populated for users with Dex-encoded user IDs.
type: string
example: okta-abc123
permissions:
$ref: '#/components/schemas/UserPermissions'
required:
- id
- email
- name
- role
- auto_groups
- status
- is_blocked
- pending_approval
UserCreateRequest:
type: object
properties:
email:
description: User's Email to send invite to
type: string
example: demo@netbird.io
name:
description: User's full name
type: string
example: Tom Schulz
role:
description: User's NetBird account role
type: string
example: admin
auto_groups:
description: Group IDs to auto-assign to peers registered by this user
type: array
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
is_service_user:
description: Is true if this user is a service user
type: boolean
example: false
required:
- role
- auto_groups
- is_service_user
UserRequest:
type: object
properties:
role:
description: User's NetBird account role
type: string
example: admin
auto_groups:
description: Group IDs to auto-assign to peers registered by this user
type: array
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
is_blocked:
description: If set to true then user is blocked and can't use the system
type: boolean
example: false
required:
- role
- auto_groups
- is_blocked
UserPermissions:
type: object
properties:
is_restricted:
type: boolean
description: Indicates whether this User's Peers view is restricted
modules:
type: object
additionalProperties:
type: object
additionalProperties:
type: boolean
propertyNames:
type: string
description: The operation type
propertyNames:
type: string
description: The module name
example: {"networks": {"read": true, "create": false, "update": false, "delete": false}, "peers": {"read": false, "create": false, "update": false, "delete": false}}
required:
- modules
- is_restricted
responses:
not_found:
description: Resource not found
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: {}
validation_failed_simple:
description: Validation failed
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: {}
bad_request:
description: Bad Request
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: {}
unprocessable:
description: Unprocessable Entity
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
type: object
properties:
message:
type: string
code:
type: integer
required:
- message
- code
internal_error:
description: Internal Server Error
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: {}
validation_failed:
description: Validation failed
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: {}
forbidden:
description: Forbidden
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: {}
requires_authentication:
description: Requires authentication
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: {}
conflict:
description: Conflict
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
X-Request-Id:
description: |
Unique identifier assigned to the request by the server and set on every
response. Useful for correlating client requests with server-side logs.
schema:
type: string
example: cot7r4n3l3vh3qj4qveg
example: cot7r4n3l3vh3qj4qveg
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
TokenAuth:
type: apiKey
in: header
name: Authorization
description: >-
Enter the token with the `Token` prefix, e.g. "Token nbp_F3f0d.....".
pathItems:
peers:
get:
summary: List all Peers
description: Returns a list of all peers
tags:
- Peers
parameters:
- name: page
in: query
description: Page number
required: false
schema:
type: integer
minimum: 1
default: 1
- name: page_size
in: query
description: Number of peers per page
required: false
schema:
type: integer
minimum: 1
maximum: 250
default: 100
- name: connected
in: query
description: Filter by peer connected status
required: false
schema:
type: boolean
- name: approval_required
in: query
description: Filter by approval_required field
required: false
schema:
type: boolean
- name: os
in: query
description: Peer os
required: false
schema:
type: array
items:
type: string
enum:
- linux
- windows
- mac
- android
- ios
- js
- name: search
in: query
description: filter peers by name, dns_label, ip, os, version, serial_number, owner name, owner email, group names, mac
required: false
schema:
type: string
security:
- BearerAuth: []
- TokenAuth: []
responses:
'200':
description: A JSON Array of Peers
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/PeerBatch'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'422':
"$ref": "#/components/responses/unprocessable"
'500':
"$ref": "#/components/responses/internal_error"
peer:
get:
summary: Retrieve a Peer
description: Get information about a peer
tags:
- Peers
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: path
name: peerId
required: true
schema:
type: string
description: The unique identifier of a peer
responses:
'200':
description: A Peer object
content:
application/json:
schema:
$ref: '#/components/schemas/Peer'
'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 a Peer
description: Update information about a peer
tags:
- Peers
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: path
name: peerId
required: true
schema:
type: string
description: The unique identifier of a peer
requestBody:
description: update a peer
required: true
content:
'application/json':
schema:
$ref: '#/components/schemas/PeerRequest'
responses:
'200':
description: A Peer object
content:
application/json:
schema:
$ref: '#/components/schemas/Peer'
'400':
"$ref": '#/components/responses/bad_request'
'401':
"$ref": '#/components/responses/requires_authentication'
'403':
"$ref": '#/components/responses/forbidden'
'422':
"$ref": "#/components/responses/unprocessable"
'500':
"$ref": '#/components/responses/internal_error'
delete:
summary: Delete a Peer
description: Delete a peer
tags:
- Peers
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: path
name: peerId
required: true
schema:
type: string
description: The unique identifier of a peer
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'
UsersPath:
get:
summary: List all Users
description: Returns a list of all users
tags:
- Users
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: query
name: service_user
schema:
type: boolean
description: Filters users and returns either regular users or service users
responses:
'200':
description: A JSON array of Users
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'422':
"$ref": "#/components/responses/unprocessable"
'500':
"$ref": "#/components/responses/internal_error"
post:
summary: Create a User
description: Creates a new service user or sends an invite to a regular user
tags:
- Users
security:
- BearerAuth: []
- TokenAuth: []
requestBody:
description: User invite information
required: true
content:
'application/json':
schema:
$ref: '#/components/schemas/UserCreateRequest'
responses:
'200':
description: A User object
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'422':
"$ref": "#/components/responses/unprocessable"
'500':
"$ref": "#/components/responses/internal_error"
UserPath:
put:
summary: Update a User
description: Update information about a User
tags:
- Users
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: path
name: userId
required: true
schema:
type: string
description: The unique identifier of a user
requestBody:
description: User update
required: true
content:
'application/json':
schema:
$ref: '#/components/schemas/UserRequest'
responses:
'200':
description: A User object
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'422':
"$ref": "#/components/responses/unprocessable"
'500':
"$ref": "#/components/responses/internal_error"
delete:
summary: Delete a User
description: This method removes a user from accessing the system. For this leaves the IDP user intact unless the `--user-delete-from-idp` is passed to management startup.
tags:
- Users
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: path
name: userId
required: true
schema:
type: string
description: The unique identifier of a user
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"
paths:
/peers:
$ref: '#/components/pathItems/peers'
/peers/{peerId}:
$ref: '#/components/pathItems/peer'
/users:
$ref: '#/components/pathItems/UsersPath'
/users/{userId}:
$ref: '#/components/pathItems/UserPath'
@@ -0,0 +1,31 @@
components:
schemas:
GroupMinimum:
type: object
properties:
id:
description: Group ID
type: string
example: ch8i4ug6lnn4g9hqv7m0
name:
description: Group Name identifier
type: string
example: devs
peers_count:
description: Count of peers associated to the group
type: integer
example: 2
resources_count:
description: Count of resources associated to the group
type: integer
example: 5
issued:
description: How the group was issued (api, integration, jwt)
type: string
enum: [ "api", "integration", "jwt" ]
example: api
required:
- id
- name
- peers_count
- resources_count
@@ -0,0 +1,250 @@
openapi: 3.1.0
servers:
- url: /api/v1alpha1
description: Default server
info:
title: NetBird REST API
description: API to manipulate groups, rules, policies and retrieve information about peers and users
version: 1.0.0-alpha1
tags:
- name: Users
description: Interact with and view information about users.
- name: Tokens
description: Interact with and view information about tokens.
- name: Peers
description: Interact with and view information about peers.
- name: Setup Keys
description: Interact with and view information about setup keys.
- name: Groups
description: Interact with and view information about groups.
- name: Policies
description: Interact with and view information about policies.
- name: Posture Checks
description: Interact with and view information about posture checks.
- name: Routes
description: Interact with and view information about routes.
- name: DNS
description: Interact with and view information about DNS configuration.
- name: DNS Zones
description: Interact with and view information about custom DNS zones.
- name: Events
description: View information about the account and network events.
- name: Accounts
description: View information about the accounts.
- name: Ingress Ports
description: Interact with and view information about the ingress peers and ports.
x-cloud-only: true
- name: Identity Providers
description: Interact with and view information about identity providers.
- name: Services
description: Interact with and view information about reverse proxy services.
- name: Instance
description: Instance setup and status endpoints for initial configuration.
- name: Jobs
description: Interact with and view information about remote jobs.
x-experimental: true
- name: Usage
description: Retrieve current usage statistics for the account.
x-cloud-only: true
- name: Subscription
description: Manage and view information about account subscriptions.
x-cloud-only: true
- name: Plans
description: Retrieve available plans and products.
x-cloud-only: true
- name: Checkout
description: Manage checkout sessions for plan subscriptions.
x-cloud-only: true
- name: AWS Marketplace
description: Manage AWS Marketplace subscriptions.
x-cloud-only: true
- name: Portal
description: Access customer portal for subscription management.
x-cloud-only: true
- name: Invoice
description: Manage and retrieve account invoices.
x-cloud-only: true
- name: MSP
description: MSP portal for Tenant management.
x-cloud-only: true
- name: IDP SCIM Integrations
description: Manage generic SCIM identity provider integrations for user and group sync.
x-cloud-only: true
- name: IDP Google Integrations
description: Manage Google Workspace identity provider integrations for user and group sync.
x-cloud-only: true
- name: IDP Azure Integrations
description: Manage Azure AD identity provider integrations for user and group sync.
x-cloud-only: true
- name: IDP Okta SCIM Integrations
description: Manage Okta SCIM identity provider integrations for user and group sync.
x-cloud-only: true
- name: EDR Intune Integrations
description: Manage Microsoft Intune EDR integrations.
x-cloud-only: true
- name: EDR SentinelOne Integrations
description: Manage SentinelOne EDR integrations.
x-cloud-only: true
- name: EDR Falcon Integrations
description: Manage CrowdStrike Falcon EDR integrations.
x-cloud-only: true
- name: EDR Huntress Integrations
description: Manage Huntress EDR integrations.
x-cloud-only: true
- name: EDR FleetDM Integrations
description: Manage FleetDM EDR integrations.
x-cloud-only: true
- name: EDR Peers
description: Manage EDR compliance bypass for peers.
x-cloud-only: true
- name: Event Streaming Integrations
description: Manage event streaming integrations.
x-cloud-only: true
- name: Notifications
description: Manage notification channels for account event alerts.
x-cloud-only: true
components:
schemas:
CountryCode:
description: 2-letter ISO 3166-1 alpha-2 code that represents the country
type: string
example: "DE"
CityName:
description: Commonly used English name of the city
type: string
example: "Berlin"
Country:
description: Describe country geographical location information
type: object
properties:
country_name:
description: Commonly used English name of the country
type: string
example: "Germany"
country_code:
$ref: '#/components/schemas/CountryCode'
required:
- country_name
- country_code
City:
description: Describe city geographical location information
type: object
properties:
geoname_id:
description: Integer ID of the record in GeoNames database
type: integer
example: 2950158
city_name:
description: Commonly used English name of the city
type: string
example: "Berlin"
required:
- geoname_id
- city_name
ErrorResponse:
type: object
description: Standard error response
properties:
message:
type: string
description: A human-readable error message.
example: "couldn't parse JSON request"
responses:
not_found:
description: Resource not found
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: { }
validation_failed_simple:
description: Validation failed
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: { }
bad_request:
description: Bad Request
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: { }
unprocessable:
description: Unprocessable Entity
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
type: object
properties:
message:
type: string
code:
type: integer
required:
- message
- code
internal_error:
description: Internal Server Error
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: { }
validation_failed:
description: Validation failed
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: { }
forbidden:
description: Forbidden
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: { }
requires_authentication:
description: Requires authentication
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content: { }
conflict:
description: Conflict
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
X-Request-Id:
description: |
Unique identifier assigned to the request by the server and set on every
response. Useful for correlating client requests with server-side logs.
schema:
type: string
example: cot7r4n3l3vh3qj4qveg
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
TokenAuth:
type: apiKey
in: header
name: Authorization
description: >-
Enter the token with the `Token` prefix, e.g. "Token nbp_F3f0d.....".
paths:
/peers:
$ref: './peer/peers.yaml'
/peers/{peerId}:
$ref: './peer/peer.yaml'
/users:
$ref: './user/user_paths.yaml#/UsersPath'
/users/{userId}:
$ref: './user/user_paths.yaml#/UserPath'
@@ -0,0 +1,257 @@
components:
schemas:
PeerRequest:
type: object
properties:
name:
type: string
example: stage-host-1
ssh_enabled:
type: boolean
example: true
login_expiration_enabled:
type: boolean
example: false
inactivity_expiration_enabled:
type: boolean
example: false
approval_required:
description: (Cloud only) Indicates whether peer needs approval
type: boolean
example: true
ip:
description: Peer's IP address
type: string
format: ipv4
example: 100.64.0.15
ipv6:
description: Peer's IPv6 overlay address. Omitted if IPv6 is not enabled for the account.
type: string
format: ipv6
example: "fd00:4e42:ab12::1"
required:
- name
- ssh_enabled
- login_expiration_enabled
- inactivity_expiration_enabled
PeerMinimum:
type: object
properties:
id:
description: Peer ID
type: string
example: chacbco6lnnbn6cg5s90
name:
description: Peer's hostname
type: string
example: stage-host-1
required:
- id
- name
Peer:
allOf:
- $ref: '#/components/schemas/PeerMinimum'
- type: object
properties:
created_at:
description: Peer creation date (UTC)
type: string
format: date-time
example: "2023-05-05T09:00:35.477782Z"
ip:
description: Peer's IP address
type: string
example: 10.64.0.1
ipv6:
description: Peer's IPv6 overlay address
type: string
format: ipv6
example: "fd00:4e42:ab12::1"
connection_ip:
description: Peer's public connection IP address
type: string
example: 35.64.0.1
connected:
description: Peer to Management connection status
type: boolean
example: true
last_seen:
description: Last time peer connected to Netbird's management service
type: string
format: date-time
example: "2023-05-05T10:05:26.420578Z"
os:
description: Peer's operating system and version
type: string
example: Darwin 13.2.1
kernel_version:
description: Peer's operating system kernel version
type: string
example: 23.2.0
geoname_id:
description: Unique identifier from the GeoNames database for a specific geographical location.
type: integer
example: 2643743
version:
description: Peer's daemon or cli version
type: string
example: 0.14.0
groups:
description: Groups that the peer belongs to
type: array
items:
$ref: '../group/components.yaml#/components/schemas/GroupMinimum'
ssh_enabled:
description: Indicates whether SSH server is enabled on this peer
type: boolean
example: true
user_id:
description: User ID of the user that enrolled this peer
type: string
example: google-oauth2|277474792786460067937
hostname:
description: Hostname of the machine
type: string
example: stage-host-1
ui_version:
description: Peer's desktop UI version
type: string
example: 0.14.0
dns_label:
description: Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
type: string
example: stage-host-1.netbird.cloud
login_expiration_enabled:
description: Indicates whether peer login expiration has been enabled or not
type: boolean
example: false
login_expired:
description: Indicates whether peer's login expired or not
type: boolean
example: false
last_login:
description: Last time this peer performed log in (authentication). E.g., user authenticated.
type: string
format: date-time
example: "2023-05-05T09:00:35.477782Z"
inactivity_expiration_enabled:
description: Indicates whether peer inactivity expiration has been enabled or not
type: boolean
example: false
approval_required:
description: (Cloud only) Indicates whether peer needs approval
type: boolean
example: true
disapproval_reason:
description: (Cloud only) Reason why the peer requires approval
type: string
country_code:
$ref: '../openapi.yaml#/components/schemas/CountryCode'
city_name:
$ref: '../openapi.yaml#/components/schemas/CityName'
serial_number:
description: System serial number
type: string
example: "C02XJ0J0JGH7"
extra_dns_labels:
description: Extra DNS labels added to the peer
type: array
items:
type: string
example: "stage-host-1"
ephemeral:
description: Indicates whether the peer is ephemeral or not
type: boolean
example: false
local_flags:
$ref: '#/components/schemas/PeerLocalFlags'
required:
- city_name
- connected
- connection_ip
- country_code
- created_at
- dns_label
- geoname_id
- groups
- hostname
- ip
- kernel_version
- last_login
- last_seen
- login_expiration_enabled
- login_expired
- inactivity_expiration_enabled
- os
- ssh_enabled
- user_id
- version
- ui_version
- approval_required
- serial_number
- extra_dns_labels
- ephemeral
PeerLocalFlags:
type: object
properties:
rosenpass_enabled:
description: Indicates whether Rosenpass is enabled on this peer
type: boolean
example: true
rosenpass_permissive:
description: Indicates whether Rosenpass is in permissive mode or not
type: boolean
example: false
server_ssh_allowed:
description: Indicates whether SSH access this peer is allowed or not
type: boolean
example: true
remote_jobs_allowed:
description: Indicates whether the peer has opted into management-requested remote jobs (e.g. debug bundles)
type: boolean
example: true
disable_client_routes:
description: Indicates whether client routes are disabled on this peer or not
type: boolean
example: false
disable_server_routes:
description: Indicates whether server routes are disabled on this peer or not
type: boolean
example: false
disable_dns:
description: Indicates whether DNS management is disabled on this peer or not
type: boolean
example: false
disable_firewall:
description: Indicates whether firewall management is disabled on this peer or not
type: boolean
example: false
block_lan_access:
description: Indicates whether LAN access is blocked on this peer when used as a routing peer
type: boolean
example: false
block_inbound:
description: Indicates whether inbound traffic is blocked on this peer
type: boolean
example: false
lazy_connection_enabled:
description: Indicates whether lazy connection is enabled on this peer
type: boolean
example: false
PeerBatch:
allOf:
- $ref: '#/components/schemas/Peer'
- type: object
properties:
created_at:
description: Peer creation date (UTC)
type: string
format: date-time
example: "2023-05-05T09:00:35.477782Z"
accessible_peers_count:
description: Number of accessible peers
type: integer
example: 5
required:
- created_at
- accessible_peers_count
@@ -0,0 +1,93 @@
get:
summary: Retrieve a Peer
description: Get information about a peer
tags: [ Peers ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
parameters:
- in: path
name: peerId
required: true
schema:
type: string
description: The unique identifier of a peer
responses:
'200':
description: A Peer object
content:
application/json:
schema:
$ref: './components.yaml#/components/schemas/Peer'
'400':
"$ref": '../openapi.yaml#/components/responses/bad_request'
'401':
"$ref": '../openapi.yaml#/components/responses/requires_authentication'
'403':
"$ref": '../openapi.yaml#/components/responses/forbidden'
'500':
"$ref": '../openapi.yaml#/components/responses/internal_error'
put:
summary: Update a Peer
description: Update information about a peer
tags: [ Peers ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
parameters:
- in: path
name: peerId
required: true
schema:
type: string
description: The unique identifier of a peer
requestBody:
description: update a peer
required: true
content:
'application/json':
schema:
$ref: './components.yaml#/components/schemas/PeerRequest'
responses:
'200':
description: A Peer object
content:
application/json:
schema:
$ref: './components.yaml#/components/schemas/Peer'
'400':
"$ref": '../openapi.yaml#/components/responses/bad_request'
'401':
"$ref": '../openapi.yaml#/components/responses/requires_authentication'
'403':
"$ref": '../openapi.yaml#/components/responses/forbidden'
'422':
"$ref": "../openapi.yaml#/components/responses/unprocessable"
'500':
"$ref": '../openapi.yaml#/components/responses/internal_error'
delete:
summary: Delete a Peer
description: Delete a peer
tags: [ Peers ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
parameters:
- in: path
name: peerId
required: true
schema:
type: string
description: The unique identifier of a peer
responses:
'200':
description: Delete status code
content: { }
'400':
"$ref": '../openapi.yaml#/components/responses/bad_request'
'401':
"$ref": '../openapi.yaml#/components/responses/requires_authentication'
'403':
"$ref": '../openapi.yaml#/components/responses/forbidden'
'500':
"$ref": '../openapi.yaml#/components/responses/internal_error'
@@ -0,0 +1,77 @@
get:
summary: List all Peers
description: Returns a list of all peers
tags: [ Peers ]
parameters:
- name: page
in: query
description: Page number
required: false
schema:
type: integer
minimum: 1
default: 1
- name: page_size
in: query
description: Number of peers per page
required: false
schema:
type: integer
minimum: 1
maximum: 250
default: 100
- name: connected
in: query
description: Filter by peer connected status
required: false
schema:
type: boolean
- name: approval_required
in: query
description: Filter by approval_required field
required: false
schema:
type: boolean
- name: os
in: query
description: Peer os
required: false
schema:
type: array
items:
type: string
enum:
- linux
- windows
- mac
- android
- ios
- js
- name: search
in: query
description: filter peers by name, dns_label, ip, os, version, serial_number, owner name, owner email, group names, mac
required: false
schema:
type: string
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
responses:
'200':
description: A JSON Array of Peers
content:
application/json:
schema:
type: array
items:
$ref: './components.yaml#/components/schemas/PeerBatch'
'400':
"$ref": "../openapi.yaml#/components/responses/bad_request"
'401':
"$ref": "../openapi.yaml#/components/responses/requires_authentication"
'403':
"$ref": "../openapi.yaml#/components/responses/forbidden"
'422':
"$ref": "../openapi.yaml#/components/responses/unprocessable"
'500':
"$ref": "../openapi.yaml#/components/responses/internal_error"
@@ -0,0 +1,93 @@
package apiv1alpha1
import (
_ "embed"
"fmt"
"log/slog"
"net/http"
"os"
"strings"
"github.com/netbirdio/netbird/shared/management/http/util"
"github.com/netbirdio/netbird/shared/management/status"
"github.com/pb33f/libopenapi"
validator "github.com/pb33f/libopenapi-validator"
"github.com/pb33f/libopenapi-validator/config"
"github.com/pb33f/libopenapi-validator/errors"
"github.com/pb33f/libopenapi/datamodel"
log "github.com/sirupsen/logrus"
)
// TODO (dmitri) this needs to be extracted, as it will grow to 500Kb
//
//go:embed bundle.yaml
var bundle []byte
func CreateV1ApiValidatingMiddleware() (*V1ValidatorMiddleware, error) {
doc, err := libopenapi.NewDocumentWithConfiguration(bundle, &datamodel.DocumentConfiguration{
Logger: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
})),
})
if err != nil {
return nil, err
}
model, err := doc.BuildV3Model()
if err != nil {
return nil, err
}
// TODO figure out document validation: rn it's possible to have a spec
// that's not entirely correct -- parts of it fail to parse, but silently
v := validator.NewValidatorFromV3Model(&model.Model,
config.WithoutSecurityValidation(),
config.WithStandardBodyDecoders(),
config.WithRejectUnsupportedBodyContent(),
config.WithRequestDefaults())
// v.SetDocument(doc)
// v.ValidatePathParams()
// if valid, errs := v.ValidateDocument(); !valid {
// return nil, fmt.Errorf("error validating OpenAPI doc, %s", errs)
// }
return &V1ValidatorMiddleware{Validator: v}, nil
}
type V1ValidatorMiddleware struct {
Validator validator.Validator
}
func (v *V1ValidatorMiddleware) Handler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
valid, errs := v.Validator.ValidateHttpRequestSync(r)
if !valid {
validationErrs := make([]string, 0, len(errs))
for _, err := range errs {
validationErrs = append(validationErrs, validationError(err))
}
log.WithContext(r.Context()).Debugf("error validating request: %s", strings.Join(validationErrs, ", "))
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "invalid request: %s", strings.Join(validationErrs, ", ")), w)
return
}
h.ServeHTTP(w, r)
})
}
func validationError(err *errors.ValidationError) string {
if err.SchemaValidationErrors != nil {
errs := make([]string, 0, len(err.SchemaValidationErrors))
for _, e := range err.SchemaValidationErrors {
errs = append(errs, fmt.Sprintf("field %s: %s", e.FieldPath, e.Reason))
}
return fmt.Sprintf("%s: %s", err.Message, strings.Join(errs, ", "))
} else {
if err.SpecLine > 0 && err.SpecCol > 0 {
return fmt.Sprintf("%s, Line: %d, Column: %d", err.Message, err.SpecLine, err.SpecCol)
} else {
return fmt.Sprint(err.Message)
}
}
}
@@ -0,0 +1,152 @@
package apiv1alpha1
import (
"log/slog"
"os"
"path/filepath"
"strings"
"unicode"
"github.com/pb33f/libopenapi"
"github.com/pb33f/libopenapi/bundler"
"github.com/pb33f/libopenapi/datamodel"
v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
"github.com/pb33f/libopenapi/generator/golang"
)
var ApiPath = filepath.Join("shared", "management", "http", "apiv1alpha1", "openapi.yaml")
func GenerateV1ApiBindings(openapipath string) ([]byte, *v3.Document, error) {
specFile, err := os.ReadFile(openapipath)
if err != nil {
return nil, nil, err
}
multiFileDoc, err := libopenapi.NewDocumentWithConfiguration(specFile, &datamodel.DocumentConfiguration{
AllowFileReferences: true,
BasePath: filepath.Dir(openapipath),
SpecFilePath: openapipath,
ExtractRefsSequentially: true,
Logger: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelError,
})),
TransformSiblingRefs: true, // enable openapi 3.1 compliance by default
MergeReferencedProperties: true, // enable enhanced resolution by default
PropertyMergeStrategy: datamodel.PreserveLocal, // local properties take precedence
})
if err != nil {
return nil, nil, err
}
multiFileModel, err := multiFileDoc.BuildV3Model()
if err != nil {
return nil, nil, err
}
bundle, err := bundler.BundleDocumentComposed(&multiFileModel.Model, &bundler.BundleCompositionConfig{
StrictValidation: true,
})
if err != nil {
return nil, nil, err
}
doc, err := libopenapi.NewDocumentWithConfiguration(bundle, &datamodel.DocumentConfiguration{
Logger: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
})),
})
if err != nil {
return nil, nil, err
}
model, err := doc.BuildV3Model()
if err != nil {
return nil, nil, err
}
return bundle, &model.Model, nil
}
func GenerateV1Schema(model *v3.Document) (*golang.GeneratedFile, error) {
// render every schema in components.schemas into one file
gen := golang.NewGenerator(
golang.WithGeneratedComment(true),
golang.WithFormatMapping("date-time", "time.Time", "time"),
golang.WithOptionalFieldsAsPointers(true),
golang.WithEnumConstants(true),
golang.WithNestedTypeNameDelimiter(""),
golang.WithPackageName("apiv1alpha1"),
golang.WithFieldNameResolver(toPublicName))
return gen.RenderSchemas(model.Components.Schemas)
}
// this is to keep existing naming of fields like "id", "url", etc
// libopenapi by default converts them to all-uppercase, like "ID", "URL", etc
func toPublicName(name string) string {
parts := splitIdentifier(name)
if len(parts) == 0 {
return "Value"
}
var b strings.Builder
for _, p := range parts {
rs := []rune(strings.ToLower(p))
rs[0] = unicode.ToUpper(rs[0])
b.WriteString(string(rs))
}
out := b.String()
first := []rune(out)[0]
if unicode.IsDigit(first) {
return "Value" + out
}
return out
}
func splitIdentifier(name string) []string {
var raw []string
var b strings.Builder
flush := func() {
if b.Len() > 0 {
raw = append(raw, b.String())
b.Reset()
}
}
for _, r := range name {
switch {
case unicode.IsLetter(r) || unicode.IsDigit(r):
b.WriteRune(r)
default:
flush()
}
}
flush()
var parts []string
for _, part := range raw {
parts = append(parts, splitCamel(part)...)
}
return parts
}
func splitCamel(value string) []string {
rs := []rune(value)
if len(rs) == 0 {
return nil
}
var parts []string
start := 0
for i := 1; i < len(rs); i++ {
prev := rs[i-1]
cur := rs[i]
var next rune
if i+1 < len(rs) {
next = rs[i+1]
}
lowerToUpper := unicode.IsLower(prev) && unicode.IsUpper(cur)
acronymToWord := unicode.IsUpper(prev) && unicode.IsUpper(cur) && next != 0 && unicode.IsLower(next)
if lowerToUpper || acronymToWord {
parts = append(parts, string(rs[start:i]))
start = i
}
}
parts = append(parts, string(rs[start:]))
return parts
}
@@ -0,0 +1,414 @@
// Code generated by libopenapi generator/golang. DO NOT EDIT.
package apiv1alpha1
import (
"encoding/json"
"time"
)
// CountryCode 2-letter ISO 3166-1 alpha-2 code that represents the country.
// CountryCode example value is defined in the OpenAPI schema.
type CountryCode string
// CityName Commonly used English name of the city.
// CityName example value is defined in the OpenAPI schema.
type CityName string
// Country Describe country geographical location information.
type Country struct {
// CountryName Commonly used English name of the country.
// CountryName example value is defined in the OpenAPI schema.
CountryName string `json:"country_name"`
CountryCode CountryCode `json:"country_code"`
}
// City Describe city geographical location information.
type City struct {
// GeonameId Integer ID of the record in GeoNames database.
// GeonameId example value is defined in the OpenAPI schema.
GeonameId int `json:"geoname_id"`
// CityName Commonly used English name of the city.
// CityName example value is defined in the OpenAPI schema.
CityName string `json:"city_name"`
}
// ErrorResponse Standard error response.
type ErrorResponse struct {
// Message A human-readable error message.
// Message example value is defined in the OpenAPI schema.
Message *string `json:"message,omitempty"`
}
type PeerBatch struct {
Peer
// CreatedAt Peer creation date (UTC).
// CreatedAt example value is defined in the OpenAPI schema.
CreatedAt time.Time `json:"created_at"`
// AccessiblePeersCount Number of accessible peers.
// AccessiblePeersCount example value is defined in the OpenAPI schema.
AccessiblePeersCount int `json:"accessible_peers_count"`
}
type PeerMinimum struct {
// Id Peer ID.
// Id example value is defined in the OpenAPI schema.
Id string `json:"id"`
// Name Peer's hostname.
// Name example value is defined in the OpenAPI schema.
Name string `json:"name"`
}
// GroupMinimumIssued How the group was issued (api, integration, jwt).
// GroupMinimumIssued example value is defined in the OpenAPI schema.
type GroupMinimumIssued string
const (
GroupMinimumIssuedAPI GroupMinimumIssued = "api"
GroupMinimumIssuedIntegration GroupMinimumIssued = "integration"
GroupMinimumIssuedJWT GroupMinimumIssued = "jwt"
)
type GroupMinimum struct {
// Id Group ID.
// Id example value is defined in the OpenAPI schema.
Id string `json:"id"`
// Name Group Name identifier.
// Name example value is defined in the OpenAPI schema.
Name string `json:"name"`
// PeersCount Count of peers associated to the group.
// PeersCount example value is defined in the OpenAPI schema.
PeersCount int `json:"peers_count"`
// ResourcesCount Count of resources associated to the group.
// ResourcesCount example value is defined in the OpenAPI schema.
ResourcesCount int `json:"resources_count"`
// Issued How the group was issued (api, integration, jwt).
// Issued example value is defined in the OpenAPI schema.
Issued *GroupMinimumIssued `json:"issued,omitempty"`
}
type PeerLocalFlags struct {
// RosenpassEnabled Indicates whether Rosenpass is enabled on this peer.
// RosenpassEnabled example value is defined in the OpenAPI schema.
RosenpassEnabled *bool `json:"rosenpass_enabled,omitempty"`
// RosenpassPermissive Indicates whether Rosenpass is in permissive mode or not.
// RosenpassPermissive example value is defined in the OpenAPI schema.
RosenpassPermissive *bool `json:"rosenpass_permissive,omitempty"`
// ServerSshAllowed Indicates whether SSH access this peer is allowed or not.
// ServerSshAllowed example value is defined in the OpenAPI schema.
ServerSshAllowed *bool `json:"server_ssh_allowed,omitempty"`
// RemoteJobsAllowed Indicates whether the peer has opted into management-requested remote jobs (e.g. debug bundles).
// RemoteJobsAllowed example value is defined in the OpenAPI schema.
RemoteJobsAllowed *bool `json:"remote_jobs_allowed,omitempty"`
// DisableClientRoutes Indicates whether client routes are disabled on this peer or not.
// DisableClientRoutes example value is defined in the OpenAPI schema.
DisableClientRoutes *bool `json:"disable_client_routes,omitempty"`
// DisableServerRoutes Indicates whether server routes are disabled on this peer or not.
// DisableServerRoutes example value is defined in the OpenAPI schema.
DisableServerRoutes *bool `json:"disable_server_routes,omitempty"`
// DisableDns Indicates whether DNS management is disabled on this peer or not.
// DisableDns example value is defined in the OpenAPI schema.
DisableDns *bool `json:"disable_dns,omitempty"`
// DisableFirewall Indicates whether firewall management is disabled on this peer or not.
// DisableFirewall example value is defined in the OpenAPI schema.
DisableFirewall *bool `json:"disable_firewall,omitempty"`
// BlockLanAccess Indicates whether LAN access is blocked on this peer when used as a routing peer.
// BlockLanAccess example value is defined in the OpenAPI schema.
BlockLanAccess *bool `json:"block_lan_access,omitempty"`
// BlockInbound Indicates whether inbound traffic is blocked on this peer.
// BlockInbound example value is defined in the OpenAPI schema.
BlockInbound *bool `json:"block_inbound,omitempty"`
// LazyConnectionEnabled Indicates whether lazy connection is enabled on this peer.
// LazyConnectionEnabled example value is defined in the OpenAPI schema.
LazyConnectionEnabled *bool `json:"lazy_connection_enabled,omitempty"`
}
type Peer struct {
PeerMinimum
// CreatedAt Peer creation date (UTC).
// CreatedAt example value is defined in the OpenAPI schema.
CreatedAt time.Time `json:"created_at"`
// Ip Peer's IP address.
// Ip example value is defined in the OpenAPI schema.
Ip string `json:"ip"`
// Ipv6 Peer's IPv6 overlay address.
// Ipv6 example value is defined in the OpenAPI schema.
Ipv6 *string `json:"ipv6,omitempty"`
// ConnectionIp Peer's public connection IP address.
// ConnectionIp example value is defined in the OpenAPI schema.
ConnectionIp string `json:"connection_ip"`
// Connected Peer to Management connection status.
// Connected example value is defined in the OpenAPI schema.
Connected bool `json:"connected"`
// LastSeen Last time peer connected to Netbird's management service.
// LastSeen example value is defined in the OpenAPI schema.
LastSeen time.Time `json:"last_seen"`
// Os Peer's operating system and version.
// Os example value is defined in the OpenAPI schema.
Os string `json:"os"`
// KernelVersion Peer's operating system kernel version.
// KernelVersion example value is defined in the OpenAPI schema.
KernelVersion string `json:"kernel_version"`
// GeonameId Unique identifier from the GeoNames database for a specific geographical location.
// GeonameId example value is defined in the OpenAPI schema.
GeonameId int `json:"geoname_id"`
// Version Peer's daemon or cli version.
// Version example value is defined in the OpenAPI schema.
Version string `json:"version"`
// Groups Groups that the peer belongs to.
Groups []GroupMinimum `json:"groups"`
// SshEnabled Indicates whether SSH server is enabled on this peer.
// SshEnabled example value is defined in the OpenAPI schema.
SshEnabled bool `json:"ssh_enabled"`
// UserId User ID of the user that enrolled this peer.
// UserId example value is defined in the OpenAPI schema.
UserId string `json:"user_id"`
// Hostname Hostname of the machine.
// Hostname example value is defined in the OpenAPI schema.
Hostname string `json:"hostname"`
// UiVersion Peer's desktop UI version.
// UiVersion example value is defined in the OpenAPI schema.
UiVersion string `json:"ui_version"`
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud.
// DnsLabel example value is defined in the OpenAPI schema.
DnsLabel string `json:"dns_label"`
// LoginExpirationEnabled Indicates whether peer login expiration has been enabled or not.
// LoginExpirationEnabled example value is defined in the OpenAPI schema.
LoginExpirationEnabled bool `json:"login_expiration_enabled"`
// LoginExpired Indicates whether peer's login expired or not.
// LoginExpired example value is defined in the OpenAPI schema.
LoginExpired bool `json:"login_expired"`
// LastLogin Last time this peer performed log in (authentication). E.g., user authenticated.
// LastLogin example value is defined in the OpenAPI schema.
LastLogin time.Time `json:"last_login"`
// InactivityExpirationEnabled Indicates whether peer inactivity expiration has been enabled or not.
// InactivityExpirationEnabled example value is defined in the OpenAPI schema.
InactivityExpirationEnabled bool `json:"inactivity_expiration_enabled"`
// ApprovalRequired (Cloud only) Indicates whether peer needs approval.
// ApprovalRequired example value is defined in the OpenAPI schema.
ApprovalRequired bool `json:"approval_required"`
// DisapprovalReason (Cloud only) Reason why the peer requires approval.
DisapprovalReason *string `json:"disapproval_reason,omitempty"`
CountryCode CountryCode `json:"country_code"`
CityName CityName `json:"city_name"`
// SerialNumber System serial number.
// SerialNumber example value is defined in the OpenAPI schema.
SerialNumber string `json:"serial_number"`
// ExtraDnsLabels Extra DNS labels added to the peer.
ExtraDnsLabels []string `json:"extra_dns_labels"`
// Ephemeral Indicates whether the peer is ephemeral or not.
// Ephemeral example value is defined in the OpenAPI schema.
Ephemeral bool `json:"ephemeral"`
LocalFlags *PeerLocalFlags `json:"local_flags,omitempty"`
}
type PeerRequest struct {
// Name example value is defined in the OpenAPI schema.
Name string `json:"name"`
// SshEnabled example value is defined in the OpenAPI schema.
SshEnabled bool `json:"ssh_enabled"`
// LoginExpirationEnabled example value is defined in the OpenAPI schema.
LoginExpirationEnabled bool `json:"login_expiration_enabled"`
// InactivityExpirationEnabled example value is defined in the OpenAPI schema.
InactivityExpirationEnabled bool `json:"inactivity_expiration_enabled"`
// ApprovalRequired (Cloud only) Indicates whether peer needs approval.
// ApprovalRequired example value is defined in the OpenAPI schema.
ApprovalRequired *bool `json:"approval_required,omitempty"`
// Ip Peer's IP address.
// Ip example value is defined in the OpenAPI schema.
Ip *string `json:"ip,omitempty"`
// Ipv6 Peer's IPv6 overlay address. Omitted if IPv6 is not enabled for the account.
// Ipv6 example value is defined in the OpenAPI schema.
Ipv6 *string `json:"ipv6,omitempty"`
}
// UserStatus User's status.
// UserStatus example value is defined in the OpenAPI schema.
type UserStatus string
const (
UserStatusActive UserStatus = "active"
UserStatusInvited UserStatus = "invited"
UserStatusBlocked UserStatus = "blocked"
)
type User struct {
// Id User ID.
// Id example value is defined in the OpenAPI schema.
Id string `json:"id"`
// Email User's email address.
// Email example value is defined in the OpenAPI schema.
Email string `json:"email"`
// Password User's password. Only present when user is created (create user endpoint is called) and only when IdP supports user creation with password.
// Password example value is defined in the OpenAPI schema.
Password *string `json:"password,omitempty"`
// Name User's name from idp provider.
// Name example value is defined in the OpenAPI schema.
Name string `json:"name"`
// Role User's NetBird account role.
// Role example value is defined in the OpenAPI schema.
Role string `json:"role"`
// Status User's status.
// Status example value is defined in the OpenAPI schema.
Status UserStatus `json:"status"`
// LastLogin Last time this user performed a login to the dashboard.
// LastLogin example value is defined in the OpenAPI schema.
LastLogin *time.Time `json:"last_login,omitempty"`
// AutoGroups Group IDs to auto-assign to peers registered by this user.
AutoGroups []string `json:"auto_groups"`
// IsCurrent Is true if authenticated user is the same as this user.
// IsCurrent readOnly.
// IsCurrent example value is defined in the OpenAPI schema.
IsCurrent *bool `json:"is_current,omitempty"`
// IsServiceUser Is true if this user is a service user.
// IsServiceUser readOnly.
// IsServiceUser example value is defined in the OpenAPI schema.
IsServiceUser *bool `json:"is_service_user,omitempty"`
// IsBlocked Is true if this user is blocked. Blocked users can't use the system.
// IsBlocked example value is defined in the OpenAPI schema.
IsBlocked bool `json:"is_blocked"`
// PendingApproval Is true if this user requires approval before being activated. Only applicable for users joining via domain matching when user_approval_required is enabled.
// PendingApproval example value is defined in the OpenAPI schema.
PendingApproval bool `json:"pending_approval"`
// Issued How user was issued by API or Integration.
// Issued example value is defined in the OpenAPI schema.
Issued *string `json:"issued,omitempty"`
// IdpId Identity provider ID (connector ID) that the user authenticated with. Only populated for users with Dex-encoded user IDs.
// IdpId example value is defined in the OpenAPI schema.
IdpId *string `json:"idp_id,omitempty"`
Permissions *UserPermissions `json:"permissions,omitempty"`
}
type UserCreateRequest struct {
// Email User's Email to send invite to.
// Email example value is defined in the OpenAPI schema.
Email *string `json:"email,omitempty"`
// Name User's full name.
// Name example value is defined in the OpenAPI schema.
Name *string `json:"name,omitempty"`
// Role User's NetBird account role.
// Role example value is defined in the OpenAPI schema.
Role string `json:"role"`
// AutoGroups Group IDs to auto-assign to peers registered by this user.
AutoGroups []string `json:"auto_groups"`
// IsServiceUser Is true if this user is a service user.
// IsServiceUser example value is defined in the OpenAPI schema.
IsServiceUser bool `json:"is_service_user"`
}
type UserRequest struct {
// Role User's NetBird account role.
// Role example value is defined in the OpenAPI schema.
Role string `json:"role"`
// AutoGroups Group IDs to auto-assign to peers registered by this user.
AutoGroups []string `json:"auto_groups"`
// IsBlocked If set to true then user is blocked and can't use the system.
// IsBlocked example value is defined in the OpenAPI schema.
IsBlocked bool `json:"is_blocked"`
}
type UserPermissionsModulesAdditionalProperty struct {
AdditionalProperties map[string]bool `json:"-"`
}
func (m *UserPermissionsModulesAdditionalProperty) UnmarshalJSON(data []byte) error {
type Alias UserPermissionsModulesAdditionalProperty
var known Alias
if err := json.Unmarshal(data, &known); err != nil {
return err
}
*m = UserPermissionsModulesAdditionalProperty(known)
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
if len(raw) == 0 {
return nil
}
m.AdditionalProperties = make(map[string]bool, len(raw))
for key, value := range raw {
var decoded bool
if err := json.Unmarshal(value, &decoded); err != nil {
return err
}
m.AdditionalProperties[key] = decoded
}
return nil
}
func (m UserPermissionsModulesAdditionalProperty) MarshalJSON() ([]byte, error) {
type Alias UserPermissionsModulesAdditionalProperty
encoded, err := json.Marshal(Alias(m))
if err != nil {
return nil, err
}
var object map[string]json.RawMessage
if err := json.Unmarshal(encoded, &object); err != nil {
return nil, err
}
for key, value := range m.AdditionalProperties {
encodedValue, err := json.Marshal(value)
if err != nil {
return nil, err
}
object[key] = encodedValue
}
return json.Marshal(object)
}
// UserPermissionsModules example value is defined in the OpenAPI schema.
type UserPermissionsModules struct {
AdditionalProperties map[string]map[string]bool `json:"-"`
}
func (m *UserPermissionsModules) UnmarshalJSON(data []byte) error {
type Alias UserPermissionsModules
var known Alias
if err := json.Unmarshal(data, &known); err != nil {
return err
}
*m = UserPermissionsModules(known)
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
if len(raw) == 0 {
return nil
}
m.AdditionalProperties = make(map[string]map[string]bool, len(raw))
for key, value := range raw {
var decoded map[string]bool
if err := json.Unmarshal(value, &decoded); err != nil {
return err
}
m.AdditionalProperties[key] = decoded
}
return nil
}
func (m UserPermissionsModules) MarshalJSON() ([]byte, error) {
type Alias UserPermissionsModules
encoded, err := json.Marshal(Alias(m))
if err != nil {
return nil, err
}
var object map[string]json.RawMessage
if err := json.Unmarshal(encoded, &object); err != nil {
return nil, err
}
for key, value := range m.AdditionalProperties {
encodedValue, err := json.Marshal(value)
if err != nil {
return nil, err
}
object[key] = encodedValue
}
return json.Marshal(object)
}
type UserPermissions struct {
// IsRestricted Indicates whether this User's Peers view is restricted.
IsRestricted bool `json:"is_restricted"`
// Modules example value is defined in the OpenAPI schema.
Modules map[string]map[string]bool `json:"modules"`
}
@@ -0,0 +1,150 @@
components:
schemas:
User:
type: object
properties:
id:
description: User ID
type: string
example: google-oauth2|277474792786460067937
email:
description: User's email address
type: string
example: demo@netbird.io
password:
description: User's password. Only present when user is created (create user endpoint is called) and only when IdP supports user creation with password.
type: string
example: super_secure_password
name:
description: User's name from idp provider
type: string
example: Tom Schulz
role:
description: User's NetBird account role
type: string
example: admin
status:
description: User's status
type: string
enum: [ "active", "invited", "blocked" ]
example: active
last_login:
description: Last time this user performed a login to the dashboard
type: string
format: date-time
example: "2023-05-05T09:00:35.477782Z"
auto_groups:
description: Group IDs to auto-assign to peers registered by this user
type: array
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
is_current:
description: Is true if authenticated user is the same as this user
type: boolean
readOnly: true
example: true
is_service_user:
description: Is true if this user is a service user
type: boolean
readOnly: true
example: false
is_blocked:
description: Is true if this user is blocked. Blocked users can't use the system
type: boolean
example: false
pending_approval:
description: Is true if this user requires approval before being activated. Only applicable for users joining via domain matching when user_approval_required is enabled.
type: boolean
example: false
issued:
description: How user was issued by API or Integration
type: string
example: api
idp_id:
description: Identity provider ID (connector ID) that the user authenticated with. Only populated for users with Dex-encoded user IDs.
type: string
example: okta-abc123
permissions:
$ref: '#/components/schemas/UserPermissions'
required:
- id
- email
- name
- role
- auto_groups
- status
- is_blocked
- pending_approval
UserPermissions:
type: object
properties:
is_restricted:
type: boolean
description: Indicates whether this User's Peers view is restricted
modules:
type: object
additionalProperties:
type: object
additionalProperties:
type: boolean
propertyNames:
type: string
description: The operation type
propertyNames:
type: string
description: The module name
example: { "networks": { "read": true, "create": false, "update": false, "delete": false }, "peers": { "read": false, "create": false, "update": false, "delete": false } }
required:
- modules
- is_restricted
UserRequest:
type: object
properties:
role:
description: User's NetBird account role
type: string
example: admin
auto_groups:
description: Group IDs to auto-assign to peers registered by this user
type: array
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
is_blocked:
description: If set to true then user is blocked and can't use the system
type: boolean
example: false
required:
- role
- auto_groups
- is_blocked
UserCreateRequest:
type: object
properties:
email:
description: User's Email to send invite to
type: string
example: demo@netbird.io
name:
description: User's full name
type: string
example: Tom Schulz
role:
description: User's NetBird account role
type: string
example: admin
auto_groups:
description: Group IDs to auto-assign to peers registered by this user
type: array
items:
type: string
example: ch8i4ug6lnn4g9hqv7m0
is_service_user:
description: Is true if this user is a service user
type: boolean
example: false
required:
- role
- auto_groups
- is_service_user
@@ -0,0 +1,129 @@
UsersPath:
get:
summary: List all Users
description: Returns a list of all users
tags: [ Users ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
parameters:
- in: query
name: service_user
schema:
type: boolean
description: Filters users and returns either regular users or service users
responses:
'200':
description: A JSON array of Users
content:
application/json:
schema:
type: array
items:
$ref: './user_components.yaml#/components/schemas/User'
'400':
"$ref": "../openapi.yaml#/components/responses/bad_request"
'401':
"$ref": "../openapi.yaml#/components/responses/requires_authentication"
'403':
"$ref": "../openapi.yaml#/components/responses/forbidden"
'422':
"$ref": "../openapi.yaml#/components/responses/unprocessable"
'500':
"$ref": "../openapi.yaml#/components/responses/internal_error"
post:
summary: Create a User
description: Creates a new service user or sends an invite to a regular user
tags: [ Users ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
requestBody:
description: User invite information
required: true
content:
'application/json':
schema:
$ref: './user_components.yaml#/components/schemas/UserCreateRequest'
responses:
'200':
description: A User object
content:
application/json:
schema:
$ref: './user_components.yaml#/components/schemas/User'
'400':
"$ref": "../openapi.yaml#/components/responses/bad_request"
'401':
"$ref": "../openapi.yaml#/components/responses/requires_authentication"
'403':
"$ref": "../openapi.yaml#/components/responses/forbidden"
'422':
"$ref": "../openapi.yaml#/components/responses/unprocessable"
'500':
"$ref": "../openapi.yaml#/components/responses/internal_error"
UserPath:
put:
summary: Update a User
description: Update information about a User
tags: [ Users ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
parameters:
- in: path
name: userId
required: true
schema:
type: string
description: The unique identifier of a user
requestBody:
description: User update
required: true
content:
'application/json':
schema:
$ref: './user_components.yaml#/components/schemas/UserRequest'
responses:
'200':
description: A User object
content:
application/json:
schema:
$ref: './user_components.yaml#/components/schemas/User'
'400':
"$ref": "../openapi.yaml#/components/responses/bad_request"
'401':
"$ref": "../openapi.yaml#/components/responses/requires_authentication"
'403':
"$ref": "../openapi.yaml#/components/responses/forbidden"
'422':
"$ref": "../openapi.yaml#/components/responses/unprocessable"
'500':
"$ref": "../openapi.yaml#/components/responses/internal_error"
delete:
summary: Delete a User
description: This method removes a user from accessing the system. For this leaves the IDP user intact unless the `--user-delete-from-idp` is passed to management startup.
tags: [ Users ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
parameters:
- in: path
name: userId
required: true
schema:
type: string
description: The unique identifier of a user
responses:
'200':
description: Delete status code
content: { }
'400':
"$ref": "../openapi.yaml#/components/responses/bad_request"
'401':
"$ref": "../openapi.yaml#/components/responses/requires_authentication"
'403':
"$ref": "../openapi.yaml#/components/responses/forbidden"
'500':
"$ref": "../openapi.yaml#/components/responses/internal_error"