Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions shared/management/client/rest/edr.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,65 @@ func (a *EDRAPI) DeleteHuntressIntegration(ctx context.Context) error {
return nil
}

// GetFleetDMIntegration retrieves the EDR FleetDM integration.
func (a *EDRAPI) GetFleetDMIntegration(ctx context.Context) (*api.EDRFleetDMResponse, error) {
resp, err := a.c.NewRequest(ctx, "GET", "/api/integrations/edr/fleetdm", nil, nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[api.EDRFleetDMResponse](resp)
return &ret, err
}

// CreateFleetDMIntegration creates a new EDR FleetDM integration.
func (a *EDRAPI) CreateFleetDMIntegration(ctx context.Context, request api.EDRFleetDMRequest) (*api.EDRFleetDMResponse, error) {
requestBytes, err := json.Marshal(request)
if err != nil {
return nil, err
}
resp, err := a.c.NewRequest(ctx, "POST", "/api/integrations/edr/fleetdm", bytes.NewReader(requestBytes), nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[api.EDRFleetDMResponse](resp)
return &ret, err
}

// UpdateFleetDMIntegration updates an existing EDR FleetDM integration.
func (a *EDRAPI) UpdateFleetDMIntegration(ctx context.Context, request api.EDRFleetDMRequest) (*api.EDRFleetDMResponse, error) {
requestBytes, err := json.Marshal(request)
if err != nil {
return nil, err
}
resp, err := a.c.NewRequest(ctx, "PUT", "/api/integrations/edr/fleetdm", bytes.NewReader(requestBytes), nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[api.EDRFleetDMResponse](resp)
return &ret, err
}

// DeleteFleetDMIntegration deletes the EDR FleetDM integration.
func (a *EDRAPI) DeleteFleetDMIntegration(ctx context.Context) error {
resp, err := a.c.NewRequest(ctx, "DELETE", "/api/integrations/edr/fleetdm", nil, nil)
if err != nil {
return err
}
if resp.Body != nil {
defer resp.Body.Close()
}
return nil
}

// BypassPeerCompliance bypasses compliance for a non-compliant peer
// See more: https://docs.netbird.io/api/resources/edr#bypass-peer-compliance
func (a *EDRAPI) BypassPeerCompliance(ctx context.Context, peerID string) (*api.BypassResponse, error) {
Expand Down
278 changes: 278 additions & 0 deletions shared/management/http/api/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ tags:
- name: EDR Huntress Integrations
description: Manage Huntress EDR integrations.
x-cloud-only: true
- name: EDR FleetDM Integrations
description: Manage FleetDM EDR integrations.
x-cloud-only: true
- name: EDR Peers
description: Manage EDR compliance bypass for peers.
x-cloud-only: true
Expand Down Expand Up @@ -4276,6 +4279,126 @@ components:
description: Status of agent firewall. Can be one of Disabled, Enabled, Pending Isolation, Isolated, Pending Release.
example: "Enabled"

EDRFleetDMRequest:
type: object
description: Request payload for creating or updating a FleetDM EDR integration
properties:
api_url:
type: string
description: FleetDM server URL
api_token:
type: string
description: FleetDM API token
groups:
type: array
description: The Groups this integrations applies to
items:
type: string
last_synced_interval:
type: integer
description: The devices last sync requirement interval in hours. Minimum value is 24 hours
minimum: 24
enabled:
type: boolean
description: Indicates whether the integration is enabled
default: true
match_attributes:
$ref: '#/components/schemas/FleetDMMatchAttributes'
required:
- api_url
- api_token
- groups
- last_synced_interval
- match_attributes
EDRFleetDMResponse:
type: object
description: Represents a FleetDM EDR integration configuration
required:
- id
- account_id
- api_url
- created_by
- last_synced_at
- created_at
- updated_at
- groups
- last_synced_interval
- match_attributes
- enabled
properties:
id:
type: integer
format: int64
description: The unique numeric identifier for the integration.
example: 123
account_id:
type: string
description: The identifier of the account this integration belongs to.
example: "ch8i4ug6lnn4g9hqv7l0"
api_url:
type: string
description: FleetDM server URL
last_synced_at:
type: string
format: date-time
description: Timestamp of when the integration was last synced.
example: "2023-05-15T10:30:00Z"
created_by:
type: string
description: The user id that created the integration
created_at:
type: string
format: date-time
description: Timestamp of when the integration was created.
example: "2023-05-15T10:30:00Z"
updated_at:
type: string
format: date-time
description: Timestamp of when the integration was last updated.
example: "2023-05-16T11:45:00Z"
groups:
type: array
description: List of groups
items:
$ref: '#/components/schemas/Group'
last_synced_interval:
type: integer
description: The devices last sync requirement interval in hours.
enabled:
type: boolean
description: Indicates whether the integration is enabled
default: true
match_attributes:
$ref: '#/components/schemas/FleetDMMatchAttributes'

FleetDMMatchAttributes:
type: object
description: Attribute conditions to match when approving FleetDM hosts. Most attributes work with FleetDM's free/open-source version. Premium-only attributes are marked accordingly
additionalProperties: false
properties:
disk_encryption_enabled:
type: boolean
description: Whether disk encryption (FileVault/BitLocker) must be enabled on the host
failing_policies_count_max:
type: integer
description: Maximum number of allowed failing policies. Use 0 to require all policies to pass
minimum: 0
example: 0
vulnerable_software_count_max:
type: integer
description: Maximum number of allowed vulnerable software on the host
minimum: 0
example: 0
status_online:
type: boolean
description: Whether the host must be online (recently seen by Fleet)
required_policies:
type: array
description: List of FleetDM policy IDs that must be passing on the host. If any of these policies is failing, the host is non-compliant
items:
type: integer
example: [1, 5, 12]

IntegrationSyncFilters:
type: object
properties:
Expand Down Expand Up @@ -10684,6 +10807,161 @@ paths:
schema:
$ref: '#/components/schemas/ErrorResponse'

/api/integrations/edr/fleetdm:
post:
tags:
- EDR FleetDM Integrations
summary: Create EDR FleetDM Integration
description: Creates a new EDR FleetDM integration
operationId: createFleetDMEDRIntegration
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EDRFleetDMRequest'
responses:
'200':
description: Integration created successfully. Returns the created integration.
content:
application/json:
schema:
$ref: '#/components/schemas/EDRFleetDMResponse'
'400':
description: Bad Request (e.g., invalid JSON, missing required fields, validation error).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized (e.g., missing or invalid authentication token).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
get:
tags:
- EDR FleetDM Integrations
summary: Get EDR FleetDM Integration
description: Retrieves a specific EDR FleetDM integration by its ID.
responses:
'200':
description: Successfully retrieved the integration details.
content:
application/json:
schema:
$ref: '#/components/schemas/EDRFleetDMResponse'
'400':
description: Bad Request (e.g., invalid integration ID format).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not Found (e.g., integration with the given ID does not exist).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Comment on lines +10852 to +10883
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Drop the nonexistent “integration ID” wording from this singleton route.

/api/integrations/edr/fleetdm has no {id} parameter, but the GET/PUT/DELETE docs still talk about invalid IDs and “the given ID”. That makes the contract self-contradictory for SDK consumers.

Suggested wording cleanup
     get:
       tags:
         - EDR FleetDM Integrations
       summary: Get EDR FleetDM Integration
-      description: Retrieves a specific EDR FleetDM integration by its ID.
+      description: Retrieves the FleetDM EDR integration configured for the authenticated account.
@@
-        '400':
-          description: Bad Request (e.g., invalid integration ID format).
+        '400':
+          description: Bad Request.
@@
-        '404':
-          description: Not Found (e.g., integration with the given ID does not exist).
+        '404':
+          description: Not Found (e.g., no FleetDM integration is configured for the authenticated account).
@@
     delete:
       tags:
         - EDR FleetDM Integrations
       summary: Delete EDR FleetDM Integration
-      description: Deletes an EDR FleetDM Integration by its ID.
+      description: Deletes the FleetDM EDR integration configured for the authenticated account.

Also applies to: 10904-10920, 10931-10958

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shared/management/http/api/openapi.yml` around lines 10852 - 10883, The
OpenAPI docs for the singleton route /api/integrations/edr/fleetdm contain
incorrect references to an "integration ID" (e.g., in the 400 and 404 response
descriptions); update the descriptions under the GET/PUT/DELETE responses for
this path so they do not mention an ID or "the given ID" and instead describe
errors in terms appropriate for a singleton resource (e.g., "Bad Request (e.g.,
invalid request format)" and "Not Found (integration does not exist)"), and
apply the same wording cleanup to the equivalent blocks referenced (the other
occurrences around lines 10904-10920 and 10931-10958).

put:
tags:
- EDR FleetDM Integrations
summary: Update EDR FleetDM Integration
description: Updates an existing EDR FleetDM Integration.
operationId: updateFleetDMEDRIntegration
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EDRFleetDMRequest'
responses:
'200':
description: Integration updated successfully. Returns the updated integration.
content:
application/json:
schema:
$ref: '#/components/schemas/EDRFleetDMResponse'
'400':
description: Bad Request (e.g., invalid JSON, validation error, invalid ID).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not Found.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags:
- EDR FleetDM Integrations
summary: Delete EDR FleetDM Integration
description: Deletes an EDR FleetDM Integration by its ID.
responses:
'200':
description: Integration deleted successfully. Returns an empty object.
content:
application/json:
schema:
type: object
example: { }
'400':
description: Bad Request (e.g., invalid integration ID format).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Not Found.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'

/api/peers/{peer-id}/edr/bypass:
parameters:
- name: peer-id
Expand Down
Loading
Loading