diff --git a/generator/api.ts b/generator/api.ts index bf351772..1bbf9ac0 100644 --- a/generator/api.ts +++ b/generator/api.ts @@ -7,13 +7,64 @@ import * as yaml from 'js-yaml'; import { merge } from 'allof-merge' import RequestBodyObject = OpenAPIV3_1.RequestBodyObject; +// Pre-processes the spec to fix allOf with conflicting enums by merging them +function fixConflictingEnumAllOf(obj: any): any { + if (obj === null || typeof obj !== 'object') { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map(item => fixConflictingEnumAllOf(item)); + } + + // Check if this object has an allOf with conflicting enums + if (obj.allOf && Array.isArray(obj.allOf)) { + const enumSchemas = obj.allOf.filter((s: any) => s.enum); + if (enumSchemas.length > 1) { + // Merge all enums into one combined enum + const combinedEnum = Array.from(new Set(enumSchemas.flatMap((s: any) => s.enum))); + const nonEnumSchemas = obj.allOf.filter((s: any) => !s.enum); + + // Merge all properties from enum schemas (type, description, example, etc.) + const mergedEnumSchema: any = { enum: combinedEnum }; + for (const s of enumSchemas) { + for (const key of Object.keys(s)) { + if (key !== 'enum' && !mergedEnumSchema[key]) { + mergedEnumSchema[key] = s[key]; + } + } + } + + if (nonEnumSchemas.length === 0) { + // All schemas had enums, replace allOf with the merged schema + const { allOf, ...rest } = obj; + return { ...rest, ...fixConflictingEnumAllOf(mergedEnumSchema) }; + } else { + // Keep non-enum schemas in allOf and add merged enum schema + return { + ...obj, + allOf: [...nonEnumSchemas.map((s: any) => fixConflictingEnumAllOf(s)), mergedEnumSchema] + }; + } + } + } + + // Recursively process all properties + const result: any = {}; + for (const key of Object.keys(obj)) { + result[key] = fixConflictingEnumAllOf(obj[key]); + } + return result; +} + export default async function gen(inputFileName: string, outputDir: string) { const specRaw = fs.readFileSync(inputFileName, 'utf8') const specYaml = yaml.load(specRaw); + const fixedSpec = fixConflictingEnumAllOf(specYaml); const onMergeError = (msg) => { throw new Error(msg) } - const merged = merge(specYaml, { onMergeError }) + const merged = merge(fixedSpec, { onMergeError }) const spec = merged as OpenAPIV3.Document diff --git a/src/pages/ipa/resources/accounts.mdx b/src/pages/ipa/resources/accounts.mdx index 86eb8cb5..bd3c42f9 100644 --- a/src/pages/ipa/resources/accounts.mdx +++ b/src/pages/ipa/resources/accounts.mdx @@ -180,13 +180,16 @@ echo $response; "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "domain": "netbird.io", "domain_category": "private", @@ -220,13 +223,16 @@ echo $response; "network_range": "string", "extra": { "peer_approval_enabled": "boolean", + "user_approval_required": "boolean", "network_traffic_logs_enabled": "boolean", "network_traffic_logs_groups": [ "string" ], "network_traffic_packet_counter_enabled": "boolean" }, - "lazy_connection_enabled": "boolean" + "lazy_connection_enabled": "boolean", + "auto_update_version": "string", + "embedded_idp_enabled": "boolean" }, "domain": "string", "domain_category": "string", @@ -504,6 +510,11 @@ echo $response; (Cloud only) Enables or disables peer approval globally. If enabled, all peers added will be in pending state until approved by an admin. + + + + Enables manual approval for new users joining via domain matching. When enabled, users are blocked with pending approval status until explicitly approved by an admin. + @@ -530,6 +541,16 @@ echo $response; Enables or disables experimental lazy connection + + + + Set Clients auto-update version. "latest", "disabled", or a specific version (e.g "0.50.1") + + + + + Indicates whether the embedded identity provider (Dex) is enabled for this account. This is a read-only field. + @@ -589,13 +610,16 @@ curl -X PUT https://api.netbird.io/api/accounts/{accountId} \ "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "onboarding": { "signup_form_pending": true, @@ -624,13 +648,16 @@ let data = JSON.stringify({ "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "onboarding": { "signup_form_pending": true, @@ -681,13 +708,16 @@ payload = json.dumps({ "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "onboarding": { "signup_form_pending": true, @@ -738,13 +768,16 @@ func main() { "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "onboarding": { "signup_form_pending": true, @@ -813,13 +846,16 @@ request.body = JSON.dump({ "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "onboarding": { "signup_form_pending": true, @@ -852,13 +888,16 @@ RequestBody body = RequestBody.create(mediaType, '{ "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "onboarding": { "signup_form_pending": true, @@ -907,13 +946,16 @@ curl_setopt_array($curl, array( "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "onboarding": { "signup_form_pending": true, @@ -957,13 +999,16 @@ echo $response; "network_range": "100.64.0.0/16", "extra": { "peer_approval_enabled": true, + "user_approval_required": false, "network_traffic_logs_enabled": true, "network_traffic_logs_groups": [ "ch8i4ug6lnn4g9hqv7m0" ], "network_traffic_packet_counter_enabled": true }, - "lazy_connection_enabled": true + "lazy_connection_enabled": true, + "auto_update_version": "0.51.2", + "embedded_idp_enabled": false }, "domain": "netbird.io", "domain_category": "private", @@ -995,13 +1040,16 @@ echo $response; "network_range": "string", "extra": { "peer_approval_enabled": "boolean", + "user_approval_required": "boolean", "network_traffic_logs_enabled": "boolean", "network_traffic_logs_groups": [ "string" ], "network_traffic_packet_counter_enabled": "boolean" }, - "lazy_connection_enabled": "boolean" + "lazy_connection_enabled": "boolean", + "auto_update_version": "string", + "embedded_idp_enabled": "boolean" }, "domain": "string", "domain_category": "string", diff --git a/src/pages/ipa/resources/dns.mdx b/src/pages/ipa/resources/dns.mdx index e2548a37..8ca013e2 100644 --- a/src/pages/ipa/resources/dns.mdx +++ b/src/pages/ipa/resources/dns.mdx @@ -1,380 +1,1878 @@ -export const description = 'Control DNS management behavior for peer groups' +export const title = 'DNS' -# DNS Settings -DNS Settings allow you to control whether NetBird manages DNS configuration for specific peer groups. This is useful when certain peers need to maintain their existing DNS setup. -## Understanding DNS Management Modes +## List all Nameserver Groups {{ tag: 'GET' , label: '/api/dns/nameservers' }} -NetBird supports two DNS management modes per peer: + + + Returns a list of all Nameserver Groups + -### Managed Mode (Default) - -When a peer's group is **not** in the disabled management list: - -- ✅ NetBird configures the system's DNS settings -- ✅ All DNS queries route through NetBird's local resolver -- ✅ Configured nameservers apply to this peer -- ✅ Centralized DNS control from the dashboard - -**Use managed mode when**: You want full control over DNS resolution for the peer. - -### Unmanaged Mode - -When a peer's group **is** in the disabled management list: - -- ✅ NetBird does not modify system DNS settings -- ✅ Peer uses its pre-existing DNS configuration -- ✅ All configured nameservers are ignored for this peer -- ✅ Peer maintains complete DNS independence - -**Use unmanaged mode when**: -- Peer has conflicting VPN or DNS requirements -- Corporate policy requires specific DNS settings -- Testing or troubleshooting DNS issues -- Peer is in a restricted environment - -### Client-Side DNS Control - -You can also disable DNS management directly on a peer using the `--disable-dns` flag: - -```bash -# Disable DNS management on this peer -netbird up --disable-dns - -# Enable DNS management on this peer -netbird up --disable-dns=true + + +```bash {{ title: 'cURL' }} +curl -X GET https://api.netbird.io/api/dns/nameservers \ +-H 'Accept: application/json' \ +-H 'Authorization: Token ' ``` -This is useful when: -- You need to disable DNS on a single peer without changing server-side settings -- Testing DNS behavior locally -- The peer has special DNS requirements not covered by group settings +```js +const axios = require('axios'); - -The `--disable-dns` flag takes precedence over server-side DNS settings. Even if the management server configures nameservers for this peer's group, the peer will ignore them when this flag is set. - +let config = { + method: 'get', + maxBodyLength: Infinity, + url: '/api/dns/nameservers', + headers: { + 'Accept': 'application/json', + 'Authorization': 'Token ' + } +}; -## Configuring DNS Settings +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` -### View Current Settings +```python +import requests +import json -1. Log in to NetBird dashboard -2. Navigate to **DNS** in the sidebar -3. Click **DNS Settings** tab +url = "https://api.netbird.io/api/dns/nameservers" -You'll see: -DNS settings +headers = { + 'Accept': 'application/json', + 'Authorization': 'Token ' +} +response = requests.request("GET", url, headers=headers) -### Disable DNS Management for a Group +print(response.text) +``` -To prevent NetBird from managing DNS for specific groups: +```go +package main -1. Go to **DNS** → **DNS Settings** -2. Click the groups selection box and select groups existing groups, or type a new group name and press enter. This will create a new group inline and disable DNS management for said new group. -3. Click 'Save Changes'. +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) - -Changes take effect within 10-30 seconds. Peers in disabled groups will revert to their original DNS settings. - +func main() { -### Re-enable DNS Management + url := "https://api.netbird.io/api/dns/nameservers" + method := "GET" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) -To restore NetBird DNS management: + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") -1. Go to **DNS** → **DNS Settings** -2. Remove the group from **Disabled Management Groups** -3. Click 'Save Changes'. + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() -The peer will start using configured nameserver groups again. + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/dns/nameservers") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Get.new(url) +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/dns/nameservers") + .method("GET") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/dns/nameservers', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', + CURLOPT_HTTPHEADER => array( + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +[ + { + "id": "ch8i4ug6lnn4g9hqv7m0", + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true + } +] +``` +```json {{ title: 'Schema' }} +[ + { + "id": "string", + "name": "string", + "description": "string", + "nameservers": [ + { + "ip": "string", + "ns_type": "string", + "port": "integer" + } + ], + "enabled": "boolean", + "groups": [ + "string" + ], + "primary": "boolean", + "domains": [ + "string" + ], + "search_domains_enabled": "boolean" + } +] +``` + + + + + --- -## Common Use Cases -### Use Case 1: VPN Conflict +## Create a Nameserver Group {{ tag: 'POST' , label: '/api/dns/nameservers' }} -**Problem**: Peers using another VPN conflict with NetBird's DNS management. + + + Creates a Nameserver Group + + ### Request-Body Parameters + + + + Name of nameserver group name + + + + + Description of the nameserver group + + + + +
+ Nameserver list + + + + + Nameserver IP + + + + + Nameserver Type + + + + + Nameserver Port + + + + + +
+ +
+ + + Nameserver group status + + + + + Distribution group IDs that defines group of peers that will use this nameserver group + + + + + Defines if a nameserver group is primary that resolves all domains. It should be true only if domains list is empty. + + + + + Match domain list. It should be empty only if primary is true. + + + + + Search domain status for match domains. It should be true only if domains list is not empty. + + +
-**Solution**: -1. Create a distribution group for VPN users (e.g., "External VPN Users") -2. Add this group to disabled management groups -3. These peers keep their VPN's DNS settings + + -### Use Case 2: Corporate DNS Policy + + +```bash {{ title: 'cURL' }} +curl -X POST https://api.netbird.io/api/dns/nameservers \ +-H 'Accept: application/json' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Token ' \ +--data-raw '{ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}' +``` -**Problem**: Company policy requires specific DNS servers on certain devices. +```js +const axios = require('axios'); +let data = JSON.stringify({ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}); +let config = { + method: 'post', + maxBodyLength: Infinity, + url: '/api/dns/nameservers', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': 'Token ' + }, + data : data +}; -**Solution**: -1. Group affected peers (e.g., "Compliance Devices") -2. Disable DNS management for this group -3. Manually configure DNS on these devices per policy +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` -### Use Case 3: Gradual Rollout +```python +import requests +import json -**Problem**: Want to test DNS changes on a subset of peers first. +url = "https://api.netbird.io/api/dns/nameservers" +payload = json.dumps({ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}) +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Token ' +} -**Solution**: -1. Create "DNS Beta" and "DNS Production" groups -2. Initially disable management for "DNS Production" -3. Test with "DNS Beta" group -4. Once validated, enable management for "DNS Production" +response = requests.request("POST", url, headers=headers, data=payload) -### Use Case 4: Troubleshooting +print(response.text) +``` -**Problem**: Suspect NetBird DNS is causing connectivity issues. +```go +package main -**Solution**: -1. Temporarily add peer's group to disabled management -2. Test if issue persists with original DNS -3. If fixed, investigate nameserver configuration -4. If not fixed, issue is unrelated to NetBird DNS +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/dns/nameservers" + method := "POST" + + payload := strings.NewReader(`{ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}`) + client := &http.Client { + } + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/dns/nameservers") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Post.new(url) +request["Content-Type"] = "application/json" +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +request.body = JSON.dump({ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}) +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); +MediaType mediaType = MediaType.parse("application/json"); +RequestBody body = RequestBody.create(mediaType, '{ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}'); +Request request = new Request.Builder() + .url("https://api.netbird.io/api/dns/nameservers") + .method("POST", body) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/dns/nameservers', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "id": "ch8i4ug6lnn4g9hqv7m0", + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +} +``` +```json {{ title: 'Schema' }} +{ + "id": "string", + "name": "string", + "description": "string", + "nameservers": [ + { + "ip": "string", + "ns_type": "string", + "port": "integer" + } + ], + "enabled": "boolean", + "groups": [ + "string" + ], + "primary": "boolean", + "domains": [ + "string" + ], + "search_domains_enabled": "boolean" +} +``` + + + + +
--- -## How Peers Behave in Each Mode -### Managed Mode Behavior +## Retrieve a Nameserver Group {{ tag: 'GET' , label: '/api/dns/nameservers/{nsgroupId}' }} -``` -Peer Startup: -1. NetBird client starts -2. Receives nameserver configuration from management -3. Configures local DNS resolver (127.0.0.1:53) -4. Updates OS DNS settings to point to 127.0.0.1 -5. Routes queries based on configured nameservers + + + Get information about a Nameserver Groups + + ### Path Parameters + + + + The unique identifier of a Nameserver Group + + + -During Operation: -- All DNS queries go through NetBird resolver -- Configuration updates apply automatically + + +```bash {{ title: 'cURL' }} +curl -X GET https://api.netbird.io/api/dns/nameservers/{nsgroupId} \ +-H 'Accept: application/json' \ +-H 'Authorization: Token ' ``` -### Unmanaged Mode Behavior +```js +const axios = require('axios'); -``` -Peer Startup: -1. NetBird client starts -2. Sees group is in disabled management list -3. Does NOT modify DNS settings -4. Does NOT start local DNS resolver for management -5. Uses existing system DNS configuration +let config = { + method: 'get', + maxBodyLength: Infinity, + url: '/api/dns/nameservers/{nsgroupId}', + headers: { + 'Accept': 'application/json', + 'Authorization': 'Token ' + } +}; -During Operation: -- DNS queries use system's configured servers -- NetBird nameservers have no effect -- NetBird provides connectivity only +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); ``` +```python +import requests +import json + +url = "https://api.netbird.io/api/dns/nameservers/{nsgroupId}" + +headers = { + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("GET", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/dns/nameservers/{nsgroupId}" + method := "GET" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/dns/nameservers/{nsgroupId}") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Get.new(url) +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/dns/nameservers/{nsgroupId}") + .method("GET") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/dns/nameservers/{nsgroupId}', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', + CURLOPT_HTTPHEADER => array( + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "id": "ch8i4ug6lnn4g9hqv7m0", + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +} +``` +```json {{ title: 'Schema' }} +{ + "id": "string", + "name": "string", + "description": "string", + "nameservers": [ + { + "ip": "string", + "ns_type": "string", + "port": "integer" + } + ], + "enabled": "boolean", + "groups": [ + "string" + ], + "primary": "boolean", + "domains": [ + "string" + ], + "search_domains_enabled": "boolean" +} +``` + + + + + + --- -## Checking Peer DNS Mode -### Linux/macOS +## Update a Nameserver Group {{ tag: 'PUT' , label: '/api/dns/nameservers/{nsgroupId}' }} -```bash -# Check if NetBird resolver is active -cat /etc/resolv.conf -# Should show: -# nameserver <100.X.X.X> (NetBird IP - managed) -# or other IPs (unmanaged) + + + Update/Replace a Nameserver Group + + ### Path Parameters + + + + The unique identifier of a Nameserver Group + + + + ### Request-Body Parameters + + + + Name of nameserver group name + + + + + Description of the nameserver group + + + + +
+ Nameserver list + + + + + Nameserver IP + + + + + Nameserver Type + + + + + Nameserver Port + + + + + +
+ +
+ + + Nameserver group status + + + + + Distribution group IDs that defines group of peers that will use this nameserver group + + + + + Defines if a nameserver group is primary that resolves all domains. It should be true only if domains list is empty. + + + + + Match domain list. It should be empty only if primary is true. + + + + + Search domain status for match domains. It should be true only if domains list is not empty. + + +
+ + + + + + +```bash {{ title: 'cURL' }} +curl -X PUT https://api.netbird.io/api/dns/nameservers/{nsgroupId} \ +-H 'Accept: application/json' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Token ' \ +--data-raw '{ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}' ``` -### Windows +```js +const axios = require('axios'); +let data = JSON.stringify({ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}); +let config = { + method: 'put', + maxBodyLength: Infinity, + url: '/api/dns/nameservers/{nsgroupId}', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': 'Token ' + }, + data : data +}; -```powershell -# Check DNS servers for NetBird adapter -Get-DnsClientServerAddress -InterfaceAlias "NetBird" - -# Managed: Shows <100.X.X.X> (NetBird IP) -# Unmanaged: Shows other servers or nothing +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); ``` -#### Using the NetBird CLI +```python +import requests +import json -```bash -# Check NetBird status -netbird status -d +url = "https://api.netbird.io/api/dns/nameservers/{nsgroupId}" +payload = json.dumps({ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}) +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("PUT", url, headers=headers, data=payload) + +print(response.text) ``` -Example Output: +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/dns/nameservers/{nsgroupId}" + method := "PUT" + + payload := strings.NewReader(`{ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}`) + client := &http.Client { + } + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} ``` -... -Nameservers: - [1.1.1.1:53] for [.] is Available -... + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/dns/nameservers/{nsgroupId}") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Put.new(url) +request["Content-Type"] = "application/json" +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +request.body = JSON.dump({ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}) +response = https.request(request) +puts response.read_body ``` ---- -## Mixing Managed and Unmanaged Peers +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); +MediaType mediaType = MediaType.parse("application/json"); +RequestBody body = RequestBody.create(mediaType, '{ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}'); +Request request = new Request.Builder() + .url("https://api.netbird.io/api/dns/nameservers/{nsgroupId}") + .method("PUT", body) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` -You can have both modes in the same network: +```php + 'https://api.netbird.io/api/dns/nameservers/{nsgroupId}', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'PUT', + CURLOPT_POSTFIELDS => '{ + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +}', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Token ' + ), +)); - -Even in unmanaged mode, peers can still communicate over the NetBird network. DNS management only affects name resolution, not connectivity. - +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "id": "ch8i4ug6lnn4g9hqv7m0", + "name": "Google DNS", + "description": "Google DNS servers", + "nameservers": [ + { + "ip": "8.8.8.8", + "ns_type": "udp", + "port": 53 + } + ], + "enabled": true, + "groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "primary": true, + "domains": [ + "example.com" + ], + "search_domains_enabled": true +} +``` +```json {{ title: 'Schema' }} +{ + "id": "string", + "name": "string", + "description": "string", + "nameservers": [ + { + "ip": "string", + "ns_type": "string", + "port": "integer" + } + ], + "enabled": "boolean", + "groups": [ + "string" + ], + "primary": "boolean", + "domains": [ + "string" + ], + "search_domains_enabled": "boolean" +} +``` + + + + +
--- -## API Configuration -You can manage DNS settings programmatically: +## Delete a Nameserver Group {{ tag: 'DELETE' , label: '/api/dns/nameservers/{nsgroupId}' }} -### Get Current Settings + + + Delete a Nameserver Group + + ### Path Parameters + + + + The unique identifier of a Nameserver Group + + + -```bash + + +```bash {{ title: 'cURL' }} +curl -X DELETE https://api.netbird.io/api/dns/nameservers/{nsgroupId} \ +-H 'Authorization: Token ' +``` + +```js +const axios = require('axios'); + +let config = { + method: 'delete', + maxBodyLength: Infinity, + url: '/api/dns/nameservers/{nsgroupId}', + headers: { + 'Authorization': 'Token ' + } +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/dns/nameservers/{nsgroupId}" + +headers = { + 'Authorization': 'Token ' +} + +response = requests.request("DELETE", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/dns/nameservers/{nsgroupId}" + method := "DELETE" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/dns/nameservers/{nsgroupId}") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Delete.new(url) +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/dns/nameservers/{nsgroupId}") + .method("DELETE") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/dns/nameservers/{nsgroupId}', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'DELETE', + CURLOPT_HTTPHEADER => array( + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + + + + +--- + + +## Retrieve DNS settings {{ tag: 'GET' , label: '/api/dns/settings' }} + + + + Returns a DNS settings object + + + + +```bash {{ title: 'cURL' }} curl -X GET https://api.netbird.io/api/dns/settings \ - -H "Authorization: Token " +-H 'Accept: application/json' \ +-H 'Authorization: Token ' ``` -### Update Settings +```js +const axios = require('axios'); -```bash -curl -X PUT https://api.netbird.io/api/dns/settings \ - -H "Authorization: Token " \ - -H "Content-Type: application/json" \ - -d '{ +let config = { + method: 'get', + maxBodyLength: Infinity, + url: '/api/dns/settings', + headers: { + 'Accept': 'application/json', + 'Authorization': 'Token ' + } +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/dns/settings" + +headers = { + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("GET", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/dns/settings" + method := "GET" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/dns/settings") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Get.new(url) +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/dns/settings") + .method("GET") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/dns/settings', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', + CURLOPT_HTTPHEADER => array( + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "items": { "disabled_management_groups": [ - "ch8i4ug6lnn4g9hqv7m0", - "ch8i4ug6lnn4g9hqv7m1" + "ch8i4ug6lnn4g9hqv7m0" ] - }' + } +} ``` - -See full [API Reference](/ipa/resources/dns) for more details. +```json {{ title: 'Schema' }} +{ + "items": { + "disabled_management_groups": [ + "string" + ] + } +} +``` + + + + + --- -## Best Practices -### 1. Default to Managed Mode +## Update DNS Settings {{ tag: 'PUT' , label: '/api/dns/settings' }} -Unless there's a specific reason, keep DNS managed for centralized control and consistency. + + + Updates a DNS settings object + + ### Request-Body Parameters + + + + Groups whose DNS management is disabled + + + -### 2. Use Groups Strategically + + -Create distribution groups that align with DNS management needs: -- ✅ Good: "External VPN Users", "Compliance Devices", "Guest Devices" -- ❌ Bad: Disabling management for individual peers repeatedly - -### 3. Document Exceptions - -Keep a record of why certain groups are unmanaged: - -``` -Disabled Management Groups: -- "External VPN Users" → Conflict with corporate VPN -- "Legacy Systems" → Cannot modify DNS (embedded systems) -- "DNS Beta" → Temporary during testing + + +```bash {{ title: 'cURL' }} +curl -X PUT https://api.netbird.io/api/dns/settings \ +-H 'Accept: application/json' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Token ' \ +--data-raw '{ + "disabled_management_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ] +}' ``` -### 4. Review Periodically +```js +const axios = require('axios'); +let data = JSON.stringify({ + "disabled_management_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ] +}); +let config = { + method: 'put', + maxBodyLength: Infinity, + url: '/api/dns/settings', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': 'Token ' + }, + data : data +}; -Regularly audit disabled groups: -- Are they still needed? -- Can peers be migrated to managed mode? -- Are there security implications? +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` -### 5. Consider Security +```python +import requests +import json -Unmanaged peers: -- May bypass corporate DNS filtering -- Could be vulnerable to DNS hijacking -- Might not respect DNS-based access controls +url = "https://api.netbird.io/api/dns/settings" +payload = json.dumps({ + "disabled_management_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ] +}) +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Token ' +} -Only use unmanaged mode when necessary. +response = requests.request("PUT", url, headers=headers, data=payload) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/dns/settings" + method := "PUT" + + payload := strings.NewReader(`{ + "disabled_management_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ] +}`) + client := &http.Client { + } + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/dns/settings") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Put.new(url) +request["Content-Type"] = "application/json" +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +request.body = JSON.dump({ + "disabled_management_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ] +}) +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); +MediaType mediaType = MediaType.parse("application/json"); +RequestBody body = RequestBody.create(mediaType, '{ + "disabled_management_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ] +}'); +Request request = new Request.Builder() + .url("https://api.netbird.io/api/dns/settings") + .method("PUT", body) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/dns/settings', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'PUT', + CURLOPT_POSTFIELDS => '{ + "disabled_management_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ] +}', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "disabled_management_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ] +} +``` +```json {{ title: 'Schema' }} +{ + "disabled_management_groups": [ + "string" + ] +} +``` + + + + + --- - -## Troubleshooting - -### Peer Not Respecting Nameservers - -**Symptom**: Configured nameservers don't apply to a peer. - -**Check**: -```bash -# On the dashboard -1. Go to DNS → DNS Settings -2. Check if peer's group is in disabled_management_groups - -# If yes → Remove from list or expected behavior -# If no → Check peer logs for errors -``` - -### Peer Reverting to Old DNS - -**Symptom**: Peer keeps using previous DNS settings after configuration change. - -**Possible causes**: -1. Group added to disabled management -2. Peer not receiving updates (connectivity issue) -3. Peer not restarted after significant change - -**Solution**: -```bash -# Restart NetBird client -netbird down -netbird up - -# Or full restart -systemctl restart netbird # Linux -# Windows: Restart NetBird service -``` - -### Cannot Disable Management for Group - -**Symptom**: Changes to DNS settings don't save or revert. - -**Check**: -- Permissions: Do you have admin rights? -- API errors: Check browser console for error messages -- Group exists: Verify the group ID is correct - ---- - -## Migration Scenarios - -### Moving from Unmanaged to Managed - -When enabling DNS management for a previously unmanaged group: - -1. **Communicate**: Warn users about DNS changes -2. **Prepare**: Create and test nameservers -3. **Schedule**: Choose low-impact time -4. **Enable**: Remove group from disabled list -5. **Verify**: Check peers are using NetBird DNS -6. **Monitor**: Watch for issues in first 24 hours - -### Moving from Managed to Unmanaged - -When disabling DNS management: - -1. **Document**: Note reason for change -2. **Disable**: Add group to disabled management -3. **Verify**: Confirm peers revert to system DNS -4. **Configure**: Manually set DNS if needed -5. **Test**: Ensure connectivity still works - ---- - -## Next Steps - -- **[Configuring Nameservers](/manage/dns/nameserver-groups)** - Configure DNS servers and domains -- **[Troubleshooting](/manage/dns/troubleshooting)** - Diagnose DNS issues -- **[API Reference](/ipa/resources/dns)** - Automate DNS settings - - -Questions about DNS settings? Check the [troubleshooting guide](/manage/dns/troubleshooting) or ask in the [NetBird community](https://netbird.io/slack). - \ No newline at end of file diff --git a/src/pages/ipa/resources/groups.mdx b/src/pages/ipa/resources/groups.mdx index 3d5ba7c7..888935a4 100644 --- a/src/pages/ipa/resources/groups.mdx +++ b/src/pages/ipa/resources/groups.mdx @@ -7,15 +7,15 @@ export const title = 'Groups' Returns a list of all groups - + ### Query Parameters - - Filter groups by name - + + Filter groups by name (exact match) + - + @@ -251,7 +251,7 @@ echo $response; ID of the resource - + Network resource type based of the address @@ -811,7 +811,7 @@ echo $response; ID of the resource - + Network resource type based of the address diff --git a/src/pages/ipa/resources/identity-providers.mdx b/src/pages/ipa/resources/identity-providers.mdx new file mode 100644 index 00000000..d97d8769 --- /dev/null +++ b/src/pages/ipa/resources/identity-providers.mdx @@ -0,0 +1,1094 @@ +export const title = 'Identity Providers' + + + +## List all Identity Providers {{ tag: 'GET' , label: '/api/identity-providers' }} + + + + Returns a list of all identity providers configured for the account + + + + +```bash {{ title: 'cURL' }} +curl -X GET https://api.netbird.io/api/identity-providers \ +-H 'Accept: application/json' \ +-H 'Authorization: Token ' +``` + +```js +const axios = require('axios'); + +let config = { + method: 'get', + maxBodyLength: Infinity, + url: '/api/identity-providers', + headers: { + 'Accept': 'application/json', + 'Authorization': 'Token ' + } +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/identity-providers" + +headers = { + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("GET", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/identity-providers" + method := "GET" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/identity-providers") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Get.new(url) +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/identity-providers") + .method("GET") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/identity-providers', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', + CURLOPT_HTTPHEADER => array( + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +[ + { + "id": "ch8i4ug6lnn4g9hqv7l0", + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com" + } +] +``` +```json {{ title: 'Schema' }} +[ + { + "id": "string", + "type": "string", + "name": "string", + "issuer": "string", + "client_id": "string" + } +] +``` + + + + + + +--- + + +## Create an Identity Provider {{ tag: 'POST' , label: '/api/identity-providers' }} + + + + Creates a new identity provider configuration + + ### Request-Body Parameters + + + + Type of identity provider + + + + + Human-readable name for the identity provider + + + + + OIDC issuer URL + + + + + OAuth2 client ID + + + + + OAuth2 client secret + + + + + + + + + +```bash {{ title: 'cURL' }} +curl -X POST https://api.netbird.io/api/identity-providers \ +-H 'Accept: application/json' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Token ' \ +--data-raw '{ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}' +``` + +```js +const axios = require('axios'); +let data = JSON.stringify({ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}); +let config = { + method: 'post', + maxBodyLength: Infinity, + url: '/api/identity-providers', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': 'Token ' + }, + data : data +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/identity-providers" +payload = json.dumps({ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}) +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("POST", url, headers=headers, data=payload) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/identity-providers" + method := "POST" + + payload := strings.NewReader(`{ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}`) + client := &http.Client { + } + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/identity-providers") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Post.new(url) +request["Content-Type"] = "application/json" +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +request.body = JSON.dump({ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}) +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); +MediaType mediaType = MediaType.parse("application/json"); +RequestBody body = RequestBody.create(mediaType, '{ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}'); +Request request = new Request.Builder() + .url("https://api.netbird.io/api/identity-providers") + .method("POST", body) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/identity-providers', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "id": "ch8i4ug6lnn4g9hqv7l0", + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com" +} +``` +```json {{ title: 'Schema' }} +{ + "id": "string", + "type": "string", + "name": "string", + "issuer": "string", + "client_id": "string" +} +``` + + + + + + +--- + + +## Retrieve an Identity Provider {{ tag: 'GET' , label: '/api/identity-providers/{idpId}' }} + + + + Get information about a specific identity provider + + ### Path Parameters + + + + The unique identifier of an identity provider + + + + + + +```bash {{ title: 'cURL' }} +curl -X GET https://api.netbird.io/api/identity-providers/{idpId} \ +-H 'Accept: application/json' \ +-H 'Authorization: Token ' +``` + +```js +const axios = require('axios'); + +let config = { + method: 'get', + maxBodyLength: Infinity, + url: '/api/identity-providers/{idpId}', + headers: { + 'Accept': 'application/json', + 'Authorization': 'Token ' + } +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/identity-providers/{idpId}" + +headers = { + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("GET", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/identity-providers/{idpId}" + method := "GET" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/identity-providers/{idpId}") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Get.new(url) +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/identity-providers/{idpId}") + .method("GET") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/identity-providers/{idpId}', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', + CURLOPT_HTTPHEADER => array( + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "id": "ch8i4ug6lnn4g9hqv7l0", + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com" +} +``` +```json {{ title: 'Schema' }} +{ + "id": "string", + "type": "string", + "name": "string", + "issuer": "string", + "client_id": "string" +} +``` + + + + + + +--- + + +## Update an Identity Provider {{ tag: 'PUT' , label: '/api/identity-providers/{idpId}' }} + + + + Update an existing identity provider configuration + + ### Path Parameters + + + + The unique identifier of an identity provider + + + + ### Request-Body Parameters + + + + Type of identity provider + + + + + Human-readable name for the identity provider + + + + + OIDC issuer URL + + + + + OAuth2 client ID + + + + + OAuth2 client secret + + + + + + + + + +```bash {{ title: 'cURL' }} +curl -X PUT https://api.netbird.io/api/identity-providers/{idpId} \ +-H 'Accept: application/json' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Token ' \ +--data-raw '{ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}' +``` + +```js +const axios = require('axios'); +let data = JSON.stringify({ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}); +let config = { + method: 'put', + maxBodyLength: Infinity, + url: '/api/identity-providers/{idpId}', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': 'Token ' + }, + data : data +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/identity-providers/{idpId}" +payload = json.dumps({ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}) +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("PUT", url, headers=headers, data=payload) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/identity-providers/{idpId}" + method := "PUT" + + payload := strings.NewReader(`{ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}`) + client := &http.Client { + } + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/identity-providers/{idpId}") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Put.new(url) +request["Content-Type"] = "application/json" +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +request.body = JSON.dump({ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}) +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); +MediaType mediaType = MediaType.parse("application/json"); +RequestBody body = RequestBody.create(mediaType, '{ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}'); +Request request = new Request.Builder() + .url("https://api.netbird.io/api/identity-providers/{idpId}") + .method("PUT", body) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/identity-providers/{idpId}', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'PUT', + CURLOPT_POSTFIELDS => '{ + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com", + "client_secret": "secret123" +}', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "id": "ch8i4ug6lnn4g9hqv7l0", + "type": "oidc", + "name": "My OIDC Provider", + "issuer": "https://accounts.google.com", + "client_id": "123456789.apps.googleusercontent.com" +} +``` +```json {{ title: 'Schema' }} +{ + "id": "string", + "type": "string", + "name": "string", + "issuer": "string", + "client_id": "string" +} +``` + + + + + + +--- + + +## Delete an Identity Provider {{ tag: 'DELETE' , label: '/api/identity-providers/{idpId}' }} + + + + Delete an identity provider configuration + + ### Path Parameters + + + + The unique identifier of an identity provider + + + + + + +```bash {{ title: 'cURL' }} +curl -X DELETE https://api.netbird.io/api/identity-providers/{idpId} \ +-H 'Authorization: Token ' +``` + +```js +const axios = require('axios'); + +let config = { + method: 'delete', + maxBodyLength: Infinity, + url: '/api/identity-providers/{idpId}', + headers: { + 'Authorization': 'Token ' + } +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/identity-providers/{idpId}" + +headers = { + 'Authorization': 'Token ' +} + +response = requests.request("DELETE", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/identity-providers/{idpId}" + method := "DELETE" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/identity-providers/{idpId}") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Delete.new(url) +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/identity-providers/{idpId}") + .method("DELETE") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/identity-providers/{idpId}', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'DELETE', + CURLOPT_HTTPHEADER => array( + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + + + + +--- diff --git a/src/pages/ipa/resources/instance.mdx b/src/pages/ipa/resources/instance.mdx new file mode 100644 index 00000000..bba047fb --- /dev/null +++ b/src/pages/ipa/resources/instance.mdx @@ -0,0 +1,418 @@ +export const title = 'Instance' + + + +## Get Instance Status {{ tag: 'GET' , label: '/api/instance' }} + + + + Returns the instance status including whether initial setup is required. This endpoint does not require authentication. + + + + +```bash {{ title: 'cURL' }} +curl -X GET https://api.netbird.io/api/instance \ +-H 'Accept: application/json' \ +-H 'Authorization: Token ' +``` + +```js +const axios = require('axios'); + +let config = { + method: 'get', + maxBodyLength: Infinity, + url: '/api/instance', + headers: { + 'Accept': 'application/json', + 'Authorization': 'Token ' + } +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/instance" + +headers = { + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("GET", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/instance" + method := "GET" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/instance") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Get.new(url) +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/instance") + .method("GET") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/instance', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'GET', + CURLOPT_HTTPHEADER => array( + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "setup_required": true +} +``` +```json {{ title: 'Schema' }} +{ + "setup_required": "boolean" +} +``` + + + + + + +--- + + +## Setup Instance {{ tag: 'POST' , label: '/api/setup' }} + + + + Creates the initial admin user for the instance. This endpoint does not require authentication but only works when setup is required (no accounts exist and embedded IDP is enabled). + + ### Request-Body Parameters + + + + Email address for the admin user + + + + + Password for the admin user (minimum 8 characters) + + + + + Display name for the admin user (defaults to email if not provided) + + + + + + + + + +```bash {{ title: 'cURL' }} +curl -X POST https://api.netbird.io/api/setup \ +-H 'Accept: application/json' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Token ' \ +--data-raw '{ + "email": "admin@example.com", + "password": "securepassword123", + "name": "Admin User" +}' +``` + +```js +const axios = require('axios'); +let data = JSON.stringify({ + "email": "admin@example.com", + "password": "securepassword123", + "name": "Admin User" +}); +let config = { + method: 'post', + maxBodyLength: Infinity, + url: '/api/setup', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': 'Token ' + }, + data : data +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/setup" +payload = json.dumps({ + "email": "admin@example.com", + "password": "securepassword123", + "name": "Admin User" +}) +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("POST", url, headers=headers, data=payload) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/setup" + method := "POST" + + payload := strings.NewReader(`{ + "email": "admin@example.com", + "password": "securepassword123", + "name": "Admin User" +}`) + client := &http.Client { + } + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/setup") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Post.new(url) +request["Content-Type"] = "application/json" +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +request.body = JSON.dump({ + "email": "admin@example.com", + "password": "securepassword123", + "name": "Admin User" +}) +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); +MediaType mediaType = MediaType.parse("application/json"); +RequestBody body = RequestBody.create(mediaType, '{ + "email": "admin@example.com", + "password": "securepassword123", + "name": "Admin User" +}'); +Request request = new Request.Builder() + .url("https://api.netbird.io/api/setup") + .method("POST", body) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/setup', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{ + "email": "admin@example.com", + "password": "securepassword123", + "name": "Admin User" +}', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "user_id": "abc123def456", + "email": "admin@example.com" +} +``` +```json {{ title: 'Schema' }} +{ + "user_id": "string", + "email": "string" +} +``` + + + + + + +--- diff --git a/src/pages/ipa/resources/peers.mdx b/src/pages/ipa/resources/peers.mdx index 5c0f98f7..a8667fb1 100644 --- a/src/pages/ipa/resources/peers.mdx +++ b/src/pages/ipa/resources/peers.mdx @@ -176,6 +176,7 @@ echo $response; { "id": "chacbco6lnnbn6cg5s90", "name": "stage-host-1", + "created_at": "2023-05-05T09:00:35.477782Z", "ip": "10.64.0.1", "connection_ip": "35.64.0.1", "connected": true, @@ -203,6 +204,10 @@ echo $response; "last_login": "2023-05-05T09:00:35.477782Z", "inactivity_expiration_enabled": false, "approval_required": true, + "disapproval_reason": { + "description": "(Cloud only) Reason why the peer requires approval", + "type": "string" + }, "country_code": "DE", "city_name": "Berlin", "serial_number": "C02XJ0J0JGH7", @@ -210,6 +215,18 @@ echo $response; "stage-host-1" ], "ephemeral": false, + "local_flags": { + "rosenpass_enabled": true, + "rosenpass_permissive": false, + "server_ssh_allowed": true, + "disable_client_routes": false, + "disable_server_routes": false, + "disable_dns": false, + "disable_firewall": false, + "block_lan_access": false, + "block_inbound": false, + "lazy_connection_enabled": false + }, "accessible_peers_count": 5 } ] @@ -219,6 +236,7 @@ echo $response; { "id": "string", "name": "string", + "created_at": "string", "ip": "string", "connection_ip": "string", "connected": "boolean", @@ -246,6 +264,7 @@ echo $response; "last_login": "string", "inactivity_expiration_enabled": "boolean", "approval_required": "boolean", + "disapproval_reason": "string", "country_code": "string", "city_name": "string", "serial_number": "string", @@ -253,6 +272,18 @@ echo $response; "string" ], "ephemeral": "boolean", + "local_flags": { + "rosenpass_enabled": "boolean", + "rosenpass_permissive": "boolean", + "server_ssh_allowed": "boolean", + "disable_client_routes": "boolean", + "disable_server_routes": "boolean", + "disable_dns": "boolean", + "disable_firewall": "boolean", + "block_lan_access": "boolean", + "block_inbound": "boolean", + "lazy_connection_enabled": "boolean" + }, "accessible_peers_count": "integer" } ] @@ -435,6 +466,7 @@ echo $response; { "id": "chacbco6lnnbn6cg5s90", "name": "stage-host-1", + "created_at": "2023-05-05T09:00:35.477782Z", "ip": "10.64.0.1", "connection_ip": "35.64.0.1", "connected": true, @@ -462,19 +494,36 @@ echo $response; "last_login": "2023-05-05T09:00:35.477782Z", "inactivity_expiration_enabled": false, "approval_required": true, + "disapproval_reason": { + "description": "(Cloud only) Reason why the peer requires approval", + "type": "string" + }, "country_code": "DE", "city_name": "Berlin", "serial_number": "C02XJ0J0JGH7", "extra_dns_labels": [ "stage-host-1" ], - "ephemeral": false + "ephemeral": false, + "local_flags": { + "rosenpass_enabled": true, + "rosenpass_permissive": false, + "server_ssh_allowed": true, + "disable_client_routes": false, + "disable_server_routes": false, + "disable_dns": false, + "disable_firewall": false, + "block_lan_access": false, + "block_inbound": false, + "lazy_connection_enabled": false + } } ``` ```json {{ title: 'Schema' }} { "id": "string", "name": "string", + "created_at": "string", "ip": "string", "connection_ip": "string", "connected": "boolean", @@ -502,13 +551,26 @@ echo $response; "last_login": "string", "inactivity_expiration_enabled": "boolean", "approval_required": "boolean", + "disapproval_reason": "string", "country_code": "string", "city_name": "string", "serial_number": "string", "extra_dns_labels": [ "string" ], - "ephemeral": "boolean" + "ephemeral": "boolean", + "local_flags": { + "rosenpass_enabled": "boolean", + "rosenpass_permissive": "boolean", + "server_ssh_allowed": "boolean", + "disable_client_routes": "boolean", + "disable_server_routes": "boolean", + "disable_dns": "boolean", + "disable_firewall": "boolean", + "block_lan_access": "boolean", + "block_inbound": "boolean", + "lazy_connection_enabled": "boolean" + } } ``` @@ -787,6 +849,7 @@ echo $response; { "id": "chacbco6lnnbn6cg5s90", "name": "stage-host-1", + "created_at": "2023-05-05T09:00:35.477782Z", "ip": "10.64.0.1", "connection_ip": "35.64.0.1", "connected": true, @@ -814,19 +877,36 @@ echo $response; "last_login": "2023-05-05T09:00:35.477782Z", "inactivity_expiration_enabled": false, "approval_required": true, + "disapproval_reason": { + "description": "(Cloud only) Reason why the peer requires approval", + "type": "string" + }, "country_code": "DE", "city_name": "Berlin", "serial_number": "C02XJ0J0JGH7", "extra_dns_labels": [ "stage-host-1" ], - "ephemeral": false + "ephemeral": false, + "local_flags": { + "rosenpass_enabled": true, + "rosenpass_permissive": false, + "server_ssh_allowed": true, + "disable_client_routes": false, + "disable_server_routes": false, + "disable_dns": false, + "disable_firewall": false, + "block_lan_access": false, + "block_inbound": false, + "lazy_connection_enabled": false + } } ``` ```json {{ title: 'Schema' }} { "id": "string", "name": "string", + "created_at": "string", "ip": "string", "connection_ip": "string", "connected": "boolean", @@ -854,13 +934,26 @@ echo $response; "last_login": "string", "inactivity_expiration_enabled": "boolean", "approval_required": "boolean", + "disapproval_reason": "string", "country_code": "string", "city_name": "string", "serial_number": "string", "extra_dns_labels": [ "string" ], - "ephemeral": "boolean" + "ephemeral": "boolean", + "local_flags": { + "rosenpass_enabled": "boolean", + "rosenpass_permissive": "boolean", + "server_ssh_allowed": "boolean", + "disable_client_routes": "boolean", + "disable_server_routes": "boolean", + "disable_dns": "boolean", + "disable_firewall": "boolean", + "block_lan_access": "boolean", + "block_inbound": "boolean", + "lazy_connection_enabled": "boolean" + } } ``` @@ -1242,3 +1335,271 @@ echo $response; --- + + +## Create a Temporary Access Peer {{ tag: 'POST' , label: '/api/peers/{peerId}/temporary-access' }} + + + + Creates a temporary access peer that can be used to access this peer and this peer only. The temporary access peer and its access policies will be automatically deleted after it disconnects. + + ### Path Parameters + + + + The unique identifier of a peer + + + + ### Request-Body Parameters + + + + Peer's hostname + + + + + Peer's WireGuard public key + + + + + List of temporary access rules + + + + + + + + + +```bash {{ title: 'cURL' }} +curl -X POST https://api.netbird.io/api/peers/{peerId}/temporary-access \ +-H 'Accept: application/json' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Token ' \ +--data-raw '{ + "name": "temp-host-1", + "wg_pub_key": "n0r3pL4c3h0ld3rK3y==", + "rules": [ + "tcp/80" + ] +}' +``` + +```js +const axios = require('axios'); +let data = JSON.stringify({ + "name": "temp-host-1", + "wg_pub_key": "n0r3pL4c3h0ld3rK3y==", + "rules": [ + "tcp/80" + ] +}); +let config = { + method: 'post', + maxBodyLength: Infinity, + url: '/api/peers/{peerId}/temporary-access', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': 'Token ' + }, + data : data +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/peers/{peerId}/temporary-access" +payload = json.dumps({ + "name": "temp-host-1", + "wg_pub_key": "n0r3pL4c3h0ld3rK3y==", + "rules": [ + "tcp/80" + ] +}) +headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("POST", url, headers=headers, data=payload) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/peers/{peerId}/temporary-access" + method := "POST" + + payload := strings.NewReader(`{ + "name": "temp-host-1", + "wg_pub_key": "n0r3pL4c3h0ld3rK3y==", + "rules": [ + "tcp/80" + ] +}`) + client := &http.Client { + } + req, err := http.NewRequest(method, url, payload) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/peers/{peerId}/temporary-access") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Post.new(url) +request["Content-Type"] = "application/json" +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +request.body = JSON.dump({ + "name": "temp-host-1", + "wg_pub_key": "n0r3pL4c3h0ld3rK3y==", + "rules": [ + "tcp/80" + ] +}) +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); +MediaType mediaType = MediaType.parse("application/json"); +RequestBody body = RequestBody.create(mediaType, '{ + "name": "temp-host-1", + "wg_pub_key": "n0r3pL4c3h0ld3rK3y==", + "rules": [ + "tcp/80" + ] +}'); +Request request = new Request.Builder() + .url("https://api.netbird.io/api/peers/{peerId}/temporary-access") + .method("POST", body) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/peers/{peerId}/temporary-access', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => '{ + "name": "temp-host-1", + "wg_pub_key": "n0r3pL4c3h0ld3rK3y==", + "rules": [ + "tcp/80" + ] +}', + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "name": "temp-host-1", + "id": "chacbco6lnnbn6cg5s90", + "rules": [ + "tcp/80" + ] +} +``` +```json {{ title: 'Schema' }} +{ + "name": "string", + "id": "string", + "rules": [ + "string" + ] +} +``` + + + + + + +--- diff --git a/src/pages/ipa/resources/policies.mdx b/src/pages/ipa/resources/policies.mdx index 7ee56d83..288b8674 100644 --- a/src/pages/ipa/resources/policies.mdx +++ b/src/pages/ipa/resources/policies.mdx @@ -186,6 +186,13 @@ echo $response; "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ { @@ -245,6 +252,13 @@ echo $response; "end": "integer" } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "string" + ] + }, "id": "string", "sources": [ { @@ -345,7 +359,7 @@ echo $response; Define if the rule is applicable in both directions, sources, and destinations. - + Policy rule type of the traffic @@ -376,6 +390,11 @@ echo $response; + + + + Map of user group ids to a list of local users + @@ -398,7 +417,7 @@ echo $response; ID of the resource - + Network resource type based of the address @@ -425,7 +444,7 @@ echo $response; ID of the resource - + Network resource type based of the address @@ -478,6 +497,13 @@ curl -X POST https://api.netbird.io/api/policies \ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -524,6 +550,13 @@ let data = JSON.stringify({ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -592,6 +625,13 @@ payload = json.dumps({ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -660,6 +700,13 @@ func main() { "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -746,6 +793,13 @@ request.body = JSON.dump({ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -796,6 +850,13 @@ RequestBody body = RequestBody.create(mediaType, '{ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -862,6 +923,13 @@ curl_setopt_array($curl, array( "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -923,6 +991,13 @@ echo $response; "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ { @@ -980,6 +1055,13 @@ echo $response; "end": "integer" } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "string" + ] + }, "id": "string", "sources": [ { @@ -1211,6 +1293,13 @@ echo $response; "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ { @@ -1268,6 +1357,13 @@ echo $response; "end": "integer" } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "string" + ] + }, "id": "string", "sources": [ { @@ -1375,7 +1471,7 @@ echo $response; Define if the rule is applicable in both directions, sources, and destinations. - + Policy rule type of the traffic @@ -1406,6 +1502,11 @@ echo $response; + + + + Map of user group ids to a list of local users + @@ -1428,7 +1529,7 @@ echo $response; ID of the resource - + Network resource type based of the address @@ -1455,7 +1556,7 @@ echo $response; ID of the resource - + Network resource type based of the address @@ -1508,6 +1609,13 @@ curl -X PUT https://api.netbird.io/api/policies/{policyId} \ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -1554,6 +1662,13 @@ let data = JSON.stringify({ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -1622,6 +1737,13 @@ payload = json.dumps({ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -1690,6 +1812,13 @@ func main() { "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -1776,6 +1905,13 @@ request.body = JSON.dump({ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -1826,6 +1962,13 @@ RequestBody body = RequestBody.create(mediaType, '{ "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -1892,6 +2035,13 @@ curl_setopt_array($curl, array( "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ "ch8i4ug6lnn4g9hqv797" @@ -1953,6 +2103,13 @@ echo $response; "end": 320 } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "group1" + ] + }, "id": "ch8i4ug6lnn4g9hqv7mg", "sources": [ { @@ -2010,6 +2167,13 @@ echo $response; "end": "integer" } ], + "authorized_groups": { + "description": "Map of user group ids to a list of local users", + "type": "object", + "additionalProperties": [ + "string" + ] + }, "id": "string", "sources": [ { diff --git a/src/pages/ipa/resources/routes.mdx b/src/pages/ipa/resources/routes.mdx index 9dfeb45a..3fd25944 100644 --- a/src/pages/ipa/resources/routes.mdx +++ b/src/pages/ipa/resources/routes.mdx @@ -183,7 +183,8 @@ echo $response; "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false } ] ``` @@ -211,7 +212,8 @@ echo $response; "keep_route": "boolean", "access_control_groups": [ "string" - ] + ], + "skip_auto_apply": "boolean" } ] ``` @@ -291,6 +293,11 @@ echo $response; Access control group identifier associated with route. + + + + Indicate if this exit node route (0.0.0.0/0) should skip auto-application for client routing + @@ -324,7 +331,8 @@ curl -X POST https://api.netbird.io/api/routes \ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }' ``` @@ -350,7 +358,8 @@ let data = JSON.stringify({ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }); let config = { method: 'post', @@ -398,7 +407,8 @@ payload = json.dumps({ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }) headers = { 'Content-Type': 'application/json', @@ -446,7 +456,8 @@ func main() { "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }`) client := &http.Client { } @@ -512,7 +523,8 @@ request.body = JSON.dump({ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }) response = https.request(request) puts response.read_body @@ -542,7 +554,8 @@ RequestBody body = RequestBody.create(mediaType, '{ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }'); Request request = new Request.Builder() .url("https://api.netbird.io/api/routes") @@ -588,7 +601,8 @@ curl_setopt_array($curl, array( "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }', CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', @@ -630,7 +644,8 @@ echo $response; "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false } ``` ```json {{ title: 'Schema' }} @@ -656,7 +671,8 @@ echo $response; "keep_route": "boolean", "access_control_groups": [ "string" - ] + ], + "skip_auto_apply": "boolean" } ``` @@ -856,7 +872,8 @@ echo $response; "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false } ``` ```json {{ title: 'Schema' }} @@ -882,7 +899,8 @@ echo $response; "keep_route": "boolean", "access_control_groups": [ "string" - ] + ], + "skip_auto_apply": "boolean" } ``` @@ -969,6 +987,11 @@ echo $response; Access control group identifier associated with route. + + + + Indicate if this exit node route (0.0.0.0/0) should skip auto-application for client routing + @@ -1002,7 +1025,8 @@ curl -X PUT https://api.netbird.io/api/routes/{routeId} \ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }' ``` @@ -1028,7 +1052,8 @@ let data = JSON.stringify({ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }); let config = { method: 'put', @@ -1076,7 +1101,8 @@ payload = json.dumps({ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }) headers = { 'Content-Type': 'application/json', @@ -1124,7 +1150,8 @@ func main() { "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }`) client := &http.Client { } @@ -1190,7 +1217,8 @@ request.body = JSON.dump({ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }) response = https.request(request) puts response.read_body @@ -1220,7 +1248,8 @@ RequestBody body = RequestBody.create(mediaType, '{ "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }'); Request request = new Request.Builder() .url("https://api.netbird.io/api/routes/{routeId}") @@ -1266,7 +1295,8 @@ curl_setopt_array($curl, array( "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false }', CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', @@ -1308,7 +1338,8 @@ echo $response; "keep_route": true, "access_control_groups": [ "chacbco6lnnbn6cg5s91" - ] + ], + "skip_auto_apply": false } ``` ```json {{ title: 'Schema' }} @@ -1334,7 +1365,8 @@ echo $response; "keep_route": "boolean", "access_control_groups": [ "string" - ] + ], + "skip_auto_apply": "boolean" } ``` diff --git a/src/pages/ipa/resources/users.mdx b/src/pages/ipa/resources/users.mdx index ffd30a46..544e02f5 100644 --- a/src/pages/ipa/resources/users.mdx +++ b/src/pages/ipa/resources/users.mdx @@ -172,6 +172,7 @@ echo $response; { "id": "google-oauth2|277474792786460067937", "email": "demo@netbird.io", + "password": "super_secure_password", "name": "Tom Schulz", "role": "admin", "status": "active", @@ -182,7 +183,9 @@ echo $response; "is_current": true, "is_service_user": false, "is_blocked": false, + "pending_approval": false, "issued": "api", + "idp_id": "okta-abc123", "permissions": { "is_restricted": { "type": "boolean", @@ -211,6 +214,7 @@ echo $response; { "id": "string", "email": "string", + "password": "string", "name": "string", "role": "string", "status": "string", @@ -221,7 +225,9 @@ echo $response; "is_current": "boolean", "is_service_user": "boolean", "is_blocked": "boolean", + "pending_approval": "boolean", "issued": "string", + "idp_id": "string", "permissions": { "is_restricted": "boolean", "modules": { @@ -521,6 +527,7 @@ echo $response; { "id": "google-oauth2|277474792786460067937", "email": "demo@netbird.io", + "password": "super_secure_password", "name": "Tom Schulz", "role": "admin", "status": "active", @@ -531,7 +538,9 @@ echo $response; "is_current": true, "is_service_user": false, "is_blocked": false, + "pending_approval": false, "issued": "api", + "idp_id": "okta-abc123", "permissions": { "is_restricted": { "type": "boolean", @@ -558,6 +567,7 @@ echo $response; { "id": "string", "email": "string", + "password": "string", "name": "string", "role": "string", "status": "string", @@ -568,7 +578,9 @@ echo $response; "is_current": "boolean", "is_service_user": "boolean", "is_blocked": "boolean", + "pending_approval": "boolean", "issued": "string", + "idp_id": "string", "permissions": { "is_restricted": "boolean", "modules": { @@ -851,6 +863,7 @@ echo $response; { "id": "google-oauth2|277474792786460067937", "email": "demo@netbird.io", + "password": "super_secure_password", "name": "Tom Schulz", "role": "admin", "status": "active", @@ -861,7 +874,9 @@ echo $response; "is_current": true, "is_service_user": false, "is_blocked": false, + "pending_approval": false, "issued": "api", + "idp_id": "okta-abc123", "permissions": { "is_restricted": { "type": "boolean", @@ -888,6 +903,7 @@ echo $response; { "id": "string", "email": "string", + "password": "string", "name": "string", "role": "string", "status": "string", @@ -898,7 +914,9 @@ echo $response; "is_current": "boolean", "is_service_user": "boolean", "is_blocked": "boolean", + "pending_approval": "boolean", "issued": "string", + "idp_id": "string", "permissions": { "is_restricted": "boolean", "modules": { @@ -1264,6 +1282,430 @@ echo $response; --- +## Approve user {{ tag: 'POST' , label: '/api/users/{userId}/approve' }} + + + + Approve a user that is pending approval + + ### Path Parameters + + + + The unique identifier of a user + + + + + + +```bash {{ title: 'cURL' }} +curl -X POST https://api.netbird.io/api/users/{userId}/approve \ +-H 'Accept: application/json' \ +-H 'Authorization: Token ' +``` + +```js +const axios = require('axios'); + +let config = { + method: 'post', + maxBodyLength: Infinity, + url: '/api/users/{userId}/approve', + headers: { + 'Accept': 'application/json', + 'Authorization': 'Token ' + } +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/users/{userId}/approve" + +headers = { + 'Accept': 'application/json', + 'Authorization': 'Token ' +} + +response = requests.request("POST", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/users/{userId}/approve" + method := "POST" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/users/{userId}/approve") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Post.new(url) +request["Accept"] = "application/json" +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/users/{userId}/approve") + .method("POST") + .addHeader("Accept", "application/json") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/users/{userId}/approve', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_HTTPHEADER => array( + 'Accept: application/json', + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + +```json {{ title: 'Example' }} +{ + "id": "google-oauth2|277474792786460067937", + "email": "demo@netbird.io", + "password": "super_secure_password", + "name": "Tom Schulz", + "role": "admin", + "status": "active", + "last_login": "2023-05-05T09:00:35.477782Z", + "auto_groups": [ + "ch8i4ug6lnn4g9hqv7m0" + ], + "is_current": true, + "is_service_user": false, + "is_blocked": false, + "pending_approval": false, + "issued": "api", + "idp_id": "okta-abc123", + "permissions": { + "is_restricted": { + "type": "boolean", + "description": "Indicates whether this User's Peers view is restricted" + }, + "modules": { + "networks": { + "read": true, + "create": false, + "update": false, + "delete": false + }, + "peers": { + "read": false, + "create": false, + "update": false, + "delete": false + } + } + } +} +``` +```json {{ title: 'Schema' }} +{ + "id": "string", + "email": "string", + "password": "string", + "name": "string", + "role": "string", + "status": "string", + "last_login": "string", + "auto_groups": [ + "string" + ], + "is_current": "boolean", + "is_service_user": "boolean", + "is_blocked": "boolean", + "pending_approval": "boolean", + "issued": "string", + "idp_id": "string", + "permissions": { + "is_restricted": "boolean", + "modules": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": "boolean", + "propertyNames": "string" + }, + "propertyNames": "string", + "example": { + "networks": { + "read": true, + "create": false, + "update": false, + "delete": false + }, + "peers": { + "read": false, + "create": false, + "update": false, + "delete": false + } + } + } + } +} +``` + + + + + + +--- + + +## Reject user {{ tag: 'DELETE' , label: '/api/users/{userId}/reject' }} + + + + Reject a user that is pending approval by removing them from the account + + ### Path Parameters + + + + The unique identifier of a user + + + + + + +```bash {{ title: 'cURL' }} +curl -X DELETE https://api.netbird.io/api/users/{userId}/reject \ +-H 'Authorization: Token ' +``` + +```js +const axios = require('axios'); + +let config = { + method: 'delete', + maxBodyLength: Infinity, + url: '/api/users/{userId}/reject', + headers: { + 'Authorization': 'Token ' + } +}; + +axios(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +``` + +```python +import requests +import json + +url = "https://api.netbird.io/api/users/{userId}/reject" + +headers = { + 'Authorization': 'Token ' +} + +response = requests.request("DELETE", url, headers=headers) + +print(response.text) +``` + +```go +package main + +import ( + "fmt" + "strings" + "net/http" + "io/ioutil" +) + +func main() { + + url := "https://api.netbird.io/api/users/{userId}/reject" + method := "DELETE" + + client := &http.Client { + } + req, err := http.NewRequest(method, url, nil) + + if err != nil { + fmt.Println(err) + return + { + + req.Header.Add("Authorization", "Token ") + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(string(body)) +} +``` + +```ruby +require "uri" +require "json" +require "net/http" + +url = URI("https://api.netbird.io/api/users/{userId}/reject") + +https = Net::HTTP.new(url.host, url.port) +https.use_ssl = true + +request = Net::HTTP::Delete.new(url) +request["Authorization"] = "Token " + +response = https.request(request) +puts response.read_body +``` + +```java +OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + +Request request = new Request.Builder() + .url("https://api.netbird.io/api/users/{userId}/reject") + .method("DELETE") + .addHeader("Authorization: Token ") + .build(); +Response response = client.newCall(request).execute(); +``` + +```php + 'https://api.netbird.io/api/users/{userId}/reject', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'DELETE', + CURLOPT_HTTPHEADER => array( + 'Authorization: Token ' + ), +)); + +$response = curl_exec($curl); + +curl_close($curl); +echo $response; +``` + + + + + + + + +--- + + ## Retrieve current user {{ tag: 'GET' , label: '/api/users/current' }} @@ -1425,6 +1867,7 @@ echo $response; { "id": "google-oauth2|277474792786460067937", "email": "demo@netbird.io", + "password": "super_secure_password", "name": "Tom Schulz", "role": "admin", "status": "active", @@ -1435,7 +1878,9 @@ echo $response; "is_current": true, "is_service_user": false, "is_blocked": false, + "pending_approval": false, "issued": "api", + "idp_id": "okta-abc123", "permissions": { "is_restricted": { "type": "boolean", @@ -1462,6 +1907,7 @@ echo $response; { "id": "string", "email": "string", + "password": "string", "name": "string", "role": "string", "status": "string", @@ -1472,7 +1918,9 @@ echo $response; "is_current": "boolean", "is_service_user": "boolean", "is_blocked": "boolean", + "pending_approval": "boolean", "issued": "string", + "idp_id": "string", "permissions": { "is_restricted": "boolean", "modules": {