mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
Feat linux firewall support (#805)
Update the client's engine to apply firewall rules received from the manager (results of ACL policy).
This commit is contained in:
committed by
GitHub
parent
2eb9a97fee
commit
ba7a39a4fc
@@ -551,49 +551,91 @@ components:
|
||||
required:
|
||||
- sources
|
||||
- destinations
|
||||
PolicyRule:
|
||||
PolicyRuleMinimum:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
description: Rule ID
|
||||
description: Policy rule ID
|
||||
type: string
|
||||
example: ch8i4ug6lnn4g9hqv7mg
|
||||
name:
|
||||
description: Rule name identifier
|
||||
description: Policy rule name identifier
|
||||
type: string
|
||||
example: Default
|
||||
description:
|
||||
description: Rule friendly description
|
||||
description: Policy rule friendly description
|
||||
type: string
|
||||
example: This is a default rule that allows connections between all the resources
|
||||
enabled:
|
||||
description: Rules status
|
||||
description: Policy rule status
|
||||
type: boolean
|
||||
example: true
|
||||
sources:
|
||||
description: policy source groups
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/GroupMinimum'
|
||||
destinations:
|
||||
description: policy destination groups
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/GroupMinimum'
|
||||
action:
|
||||
description: policy accept or drops packets
|
||||
description: Policy rule accept or drops packets
|
||||
type: string
|
||||
enum: ["accept","drop"]
|
||||
example: accept
|
||||
bidirectional:
|
||||
description: Define if the rule is applicable in both directions, sources, and destinations.
|
||||
type: boolean
|
||||
example: true
|
||||
protocol:
|
||||
description: Policy rule type of the traffic
|
||||
type: string
|
||||
enum: ["all", "tcp", "udp", "icmp"]
|
||||
example: "tcp"
|
||||
ports:
|
||||
description: Policy rule affected ports or it ranges list
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: [80,443]
|
||||
required:
|
||||
- name
|
||||
- sources
|
||||
- destinations
|
||||
- action
|
||||
- enabled
|
||||
- bidirectional
|
||||
- protocol
|
||||
- action
|
||||
PolicyRuleUpdate:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/PolicyRuleMinimum'
|
||||
- type: object
|
||||
properties:
|
||||
sources:
|
||||
description: Policy rule source groups
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
destinations:
|
||||
description: Policy rule destination groups
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
required:
|
||||
- sources
|
||||
- destinations
|
||||
PolicyRule:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/PolicyRuleMinimum'
|
||||
- type: object
|
||||
properties:
|
||||
sources:
|
||||
description: Policy rule source groups
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/GroupMinimum'
|
||||
destinations:
|
||||
description: Policy rule destination groups
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/GroupMinimum'
|
||||
required:
|
||||
- sources
|
||||
- destinations
|
||||
PolicyMinimum:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
description: Policy ID
|
||||
type: string
|
||||
name:
|
||||
description: Policy name identifier
|
||||
type: string
|
||||
@@ -609,29 +651,35 @@ components:
|
||||
query:
|
||||
description: Policy Rego query
|
||||
type: string
|
||||
example: package netbird\n\nall[rule] {\n is_peer_in_any_group([\"ch8i4ug6lnn4g9hqv7m0\",\"ch8i4ug6lnn4g9hqv7m0\"])\n rule := {\n rules_from_group(\"ch8i4ug6lnn4g9hqv7m0\", \"dst\", \"accept\", \"\"),\n rules_from_group(\"ch8i4ug6lnn4g9hqv7m0\", \"src\", \"accept\", \"\"),\n }[_][_]\n}\n
|
||||
rules:
|
||||
description: Policy rule object for policy UI editor
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PolicyRule'
|
||||
required:
|
||||
- name
|
||||
- description
|
||||
- enabled
|
||||
- query
|
||||
- rules
|
||||
PolicyUpdate:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/PolicyMinimum'
|
||||
- type: object
|
||||
properties:
|
||||
rules:
|
||||
description: Policy rule object for policy UI editor
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PolicyRuleUpdate'
|
||||
required:
|
||||
- rules
|
||||
Policy:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/PolicyMinimum'
|
||||
- type: object
|
||||
properties:
|
||||
id:
|
||||
description: Policy ID
|
||||
type: string
|
||||
example: ch8i4ug6lnn4g9hqv7mg
|
||||
rules:
|
||||
description: Policy rule object for policy UI editor
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PolicyRule'
|
||||
required:
|
||||
- id
|
||||
- rules
|
||||
RouteRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -884,7 +932,7 @@ security:
|
||||
paths:
|
||||
/api/accounts:
|
||||
get:
|
||||
summary: List all Accounts
|
||||
summary: List all accounts
|
||||
description: Returns a list of accounts of a user. Always returns a list of one account.
|
||||
tags: [ Accounts ]
|
||||
security:
|
||||
@@ -909,7 +957,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/accounts/{accountId}:
|
||||
put:
|
||||
summary: Update an Account
|
||||
summary: Update an account
|
||||
description: Update information about an account
|
||||
tags: [ Accounts ]
|
||||
security:
|
||||
@@ -950,7 +998,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/users:
|
||||
get:
|
||||
summary: List all Users
|
||||
summary: List all users
|
||||
description: Returns a list of all users
|
||||
tags: [ Users ]
|
||||
security:
|
||||
@@ -980,7 +1028,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a User
|
||||
summary: Create a user
|
||||
description: Creates a new service user or sends an invite to a regular user
|
||||
tags: [ Users ]
|
||||
security:
|
||||
@@ -1009,7 +1057,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/users/{userId}:
|
||||
put:
|
||||
summary: Update a User
|
||||
summary: Update a user
|
||||
description: Update information about a User
|
||||
tags: [ Users ]
|
||||
security:
|
||||
@@ -1044,8 +1092,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a User
|
||||
description: Delete a User
|
||||
summary: Delete a user
|
||||
description: Delete a user
|
||||
tags: [ Users ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1071,7 +1119,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/users/{userId}/tokens:
|
||||
get:
|
||||
summary: List all Tokens
|
||||
summary: List all tokens
|
||||
description: Returns a list of all tokens for a user
|
||||
tags: [ Tokens ]
|
||||
security:
|
||||
@@ -1102,7 +1150,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Token
|
||||
summary: Create a token
|
||||
description: Create a new token for a user
|
||||
tags: [ Tokens ]
|
||||
security:
|
||||
@@ -1138,7 +1186,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/users/{userId}/tokens/{tokenId}:
|
||||
get:
|
||||
summary: Retrieve a Token
|
||||
summary: Retrieve a token
|
||||
description: Returns a specific token for a user
|
||||
tags: [ Tokens ]
|
||||
security:
|
||||
@@ -1173,7 +1221,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Token
|
||||
summary: Delete a token
|
||||
description: Delete a token for a user
|
||||
tags: [ Tokens ]
|
||||
security:
|
||||
@@ -1206,7 +1254,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/peers:
|
||||
get:
|
||||
summary: List all Peers
|
||||
summary: List all peers
|
||||
description: Returns a list of all peers
|
||||
tags: [ Peers ]
|
||||
security:
|
||||
@@ -1231,7 +1279,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/peers/{peerId}:
|
||||
get:
|
||||
summary: Retrieve a Peer
|
||||
summary: Retrieve a peer
|
||||
description: Get information about a peer
|
||||
tags: [ Peers ]
|
||||
security:
|
||||
@@ -1260,7 +1308,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Peer
|
||||
summary: Update a peer
|
||||
description: Update information about a peer
|
||||
tags: [ Peers ]
|
||||
security:
|
||||
@@ -1295,7 +1343,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Peer
|
||||
summary: Delete a peer
|
||||
description: Delete a peer
|
||||
tags: [ Peers ]
|
||||
security:
|
||||
@@ -1322,7 +1370,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/setup-keys:
|
||||
get:
|
||||
summary: List all Setup Keys
|
||||
summary: List all setup keys
|
||||
description: Returns a list of all Setup Keys
|
||||
tags: [ Setup Keys ]
|
||||
security:
|
||||
@@ -1346,8 +1394,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Setup Key
|
||||
description: Creates a Setup Key
|
||||
summary: Create a setup key
|
||||
description: Creates a setup key
|
||||
tags: [ Setup Keys ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1375,8 +1423,8 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/setup-keys/{keyId}:
|
||||
get:
|
||||
summary: Retrieve a Setup Key
|
||||
description: Get information about a Setup Key
|
||||
summary: Retrieve a setup key
|
||||
description: Get information about a setup key
|
||||
tags: [ Setup Keys ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1404,8 +1452,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Setup Key
|
||||
description: Update information about a Setup Key
|
||||
summary: Update a setup key
|
||||
description: Update information about a setup key
|
||||
tags: [ Setup Keys ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1440,8 +1488,8 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/groups:
|
||||
get:
|
||||
summary: List all Groups
|
||||
description: Returns a list of all Groups
|
||||
summary: List all groups
|
||||
description: Returns a list of all groups
|
||||
tags: [ Groups ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1464,8 +1512,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Group
|
||||
description: Creates a Group
|
||||
summary: Create a group
|
||||
description: Creates a group
|
||||
tags: [ Groups ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1493,8 +1541,8 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/groups/{groupId}:
|
||||
get:
|
||||
summary: Retrieve a Group
|
||||
description: Get information about a Group
|
||||
summary: Retrieve a group
|
||||
description: Get information about a group
|
||||
tags: [ Groups ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1522,8 +1570,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Group
|
||||
description: Update/Replace a Group
|
||||
summary: Update a group
|
||||
description: Update/Replace a group
|
||||
tags: [ Groups ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1558,7 +1606,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Group
|
||||
description: Delete a Group
|
||||
description: Delete a group
|
||||
tags: [ Groups ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1584,8 +1632,8 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/rules:
|
||||
get:
|
||||
summary: List all Rules
|
||||
description: Returns a list of all Rules
|
||||
summary: List all rules
|
||||
description: Returns a list of all rules
|
||||
tags: [ Rules ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1608,8 +1656,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Rule
|
||||
description: Creates a Rule
|
||||
summary: Create a rule
|
||||
description: Creates a rule
|
||||
tags: [ Rules ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1629,8 +1677,8 @@ paths:
|
||||
$ref: '#/components/schemas/Rule'
|
||||
/api/rules/{ruleId}:
|
||||
get:
|
||||
summary: Retrieve a Rule
|
||||
description: Get information about a Rules
|
||||
summary: Retrieve a rule
|
||||
description: Get information about a rules
|
||||
tags: [ Rules ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1658,8 +1706,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Rule
|
||||
description: Update/Replace a Rule
|
||||
summary: Update a rule
|
||||
description: Update/Replace a rule
|
||||
tags: [ Rules ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1693,8 +1741,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Rule
|
||||
description: Delete a Rule
|
||||
summary: Delete a rule
|
||||
description: Delete a rule
|
||||
tags: [ Rules ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1720,8 +1768,8 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/policies:
|
||||
get:
|
||||
summary: List all Policies
|
||||
description: Returns a list of all Policies
|
||||
summary: List all policies
|
||||
description: Returns a list of all policies
|
||||
tags: [ Policies ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1744,8 +1792,8 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Policy
|
||||
description: Creates a Policy
|
||||
summary: Create a policy
|
||||
description: Creates a policy
|
||||
tags: [ Policies ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1755,7 +1803,7 @@ paths:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: '#/components/schemas/PolicyMinimum'
|
||||
$ref: '#/components/schemas/PolicyUpdate'
|
||||
responses:
|
||||
'200':
|
||||
description: A Policy Object
|
||||
@@ -1765,7 +1813,7 @@ paths:
|
||||
$ref: '#/components/schemas/Policy'
|
||||
/api/policies/{policyId}:
|
||||
get:
|
||||
summary: Retrieve a Policy
|
||||
summary: Retrieve a policy
|
||||
description: Get information about a Policies
|
||||
tags: [ Policies ]
|
||||
security:
|
||||
@@ -1794,7 +1842,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Policy
|
||||
summary: Update a policy
|
||||
description: Update/Replace a Policy
|
||||
tags: [ Policies ]
|
||||
security:
|
||||
@@ -1812,7 +1860,7 @@ paths:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: '#/components/schemas/PolicyMinimum'
|
||||
$ref: '#/components/schemas/PolicyUpdate'
|
||||
responses:
|
||||
'200':
|
||||
description: A Policy object
|
||||
@@ -1830,7 +1878,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Policy
|
||||
description: Delete a Policy
|
||||
description: Delete a policy
|
||||
tags: [ Policies ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -1856,7 +1904,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/routes:
|
||||
get:
|
||||
summary: List all Routes
|
||||
summary: List all routes
|
||||
description: Returns a list of all routes
|
||||
tags: [ Routes ]
|
||||
security:
|
||||
@@ -1880,7 +1928,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Route
|
||||
summary: Create a route
|
||||
description: Creates a Route
|
||||
tags: [ Routes ]
|
||||
security:
|
||||
@@ -1910,7 +1958,7 @@ paths:
|
||||
|
||||
/api/routes/{routeId}:
|
||||
get:
|
||||
summary: Retrieve a Route
|
||||
summary: Retrieve a route
|
||||
description: Get information about a Routes
|
||||
tags: [ Routes ]
|
||||
security:
|
||||
@@ -1939,7 +1987,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Route
|
||||
summary: Update a route
|
||||
description: Update/Replace a Route
|
||||
tags: [ Routes ]
|
||||
security:
|
||||
@@ -1975,7 +2023,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Route
|
||||
description: Delete a Route
|
||||
description: Delete a route
|
||||
tags: [ Routes ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
@@ -2001,7 +2049,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/dns/nameservers:
|
||||
get:
|
||||
summary: List all Nameserver Groups
|
||||
summary: List all nameserver groups
|
||||
description: Returns a list of all Nameserver Groups
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
@@ -2025,7 +2073,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Nameserver Group
|
||||
summary: Create a nameserver group
|
||||
description: Creates a Nameserver Group
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
@@ -2052,9 +2100,10 @@ paths:
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
|
||||
/api/dns/nameservers/{nsgroupId}:
|
||||
get:
|
||||
summary: Retrieve a Nameserver Group
|
||||
summary: Retrieve a nameserver group
|
||||
description: Get information about a Nameserver Groups
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
@@ -2083,7 +2132,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Nameserver Group
|
||||
summary: Update a nameserver group
|
||||
description: Update/Replace a Nameserver Group
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
@@ -2118,7 +2167,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Nameserver Group
|
||||
summary: Delete a nameserver group
|
||||
description: Delete a Nameserver Group
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
@@ -2143,9 +2192,10 @@ paths:
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
|
||||
/api/dns/settings:
|
||||
get:
|
||||
summary: Retrieve DNS Settings
|
||||
summary: Retrieve DNS settings
|
||||
description: Returns a DNS settings object
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
@@ -2168,7 +2218,7 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update DNS Settings
|
||||
summary: Update DNS settings
|
||||
description: Updates a DNS settings object
|
||||
tags: [ DNS ]
|
||||
security:
|
||||
@@ -2197,7 +2247,7 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/events:
|
||||
get:
|
||||
summary: List all Events
|
||||
summary: List all events
|
||||
description: Returns a list of all events
|
||||
tags: [ Events ]
|
||||
security:
|
||||
|
||||
@@ -72,6 +72,42 @@ const (
|
||||
PolicyRuleActionDrop PolicyRuleAction = "drop"
|
||||
)
|
||||
|
||||
// Defines values for PolicyRuleProtocol.
|
||||
const (
|
||||
PolicyRuleProtocolAll PolicyRuleProtocol = "all"
|
||||
PolicyRuleProtocolIcmp PolicyRuleProtocol = "icmp"
|
||||
PolicyRuleProtocolTcp PolicyRuleProtocol = "tcp"
|
||||
PolicyRuleProtocolUdp PolicyRuleProtocol = "udp"
|
||||
)
|
||||
|
||||
// Defines values for PolicyRuleMinimumAction.
|
||||
const (
|
||||
PolicyRuleMinimumActionAccept PolicyRuleMinimumAction = "accept"
|
||||
PolicyRuleMinimumActionDrop PolicyRuleMinimumAction = "drop"
|
||||
)
|
||||
|
||||
// Defines values for PolicyRuleMinimumProtocol.
|
||||
const (
|
||||
PolicyRuleMinimumProtocolAll PolicyRuleMinimumProtocol = "all"
|
||||
PolicyRuleMinimumProtocolIcmp PolicyRuleMinimumProtocol = "icmp"
|
||||
PolicyRuleMinimumProtocolTcp PolicyRuleMinimumProtocol = "tcp"
|
||||
PolicyRuleMinimumProtocolUdp PolicyRuleMinimumProtocol = "udp"
|
||||
)
|
||||
|
||||
// Defines values for PolicyRuleUpdateAction.
|
||||
const (
|
||||
PolicyRuleUpdateActionAccept PolicyRuleUpdateAction = "accept"
|
||||
PolicyRuleUpdateActionDrop PolicyRuleUpdateAction = "drop"
|
||||
)
|
||||
|
||||
// Defines values for PolicyRuleUpdateProtocol.
|
||||
const (
|
||||
PolicyRuleUpdateProtocolAll PolicyRuleUpdateProtocol = "all"
|
||||
PolicyRuleUpdateProtocolIcmp PolicyRuleUpdateProtocol = "icmp"
|
||||
PolicyRuleUpdateProtocolTcp PolicyRuleUpdateProtocol = "tcp"
|
||||
PolicyRuleUpdateProtocolUdp PolicyRuleUpdateProtocol = "udp"
|
||||
)
|
||||
|
||||
// Defines values for UserStatus.
|
||||
const (
|
||||
UserStatusActive UserStatus = "active"
|
||||
@@ -344,7 +380,7 @@ type Policy struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Policy ID
|
||||
Id string `json:"id"`
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Name Policy name identifier
|
||||
Name string `json:"name"`
|
||||
@@ -364,6 +400,138 @@ type PolicyMinimum struct {
|
||||
// Enabled Policy status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Policy ID
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Name Policy name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// Query Policy Rego query
|
||||
Query string `json:"query"`
|
||||
}
|
||||
|
||||
// PolicyRule defines model for PolicyRule.
|
||||
type PolicyRule struct {
|
||||
// Action Policy rule accept or drops packets
|
||||
Action PolicyRuleAction `json:"action"`
|
||||
|
||||
// Bidirectional Define if the rule is applicable in both directions, sources, and destinations.
|
||||
Bidirectional bool `json:"bidirectional"`
|
||||
|
||||
// Description Policy rule friendly description
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// Destinations Policy rule destination groups
|
||||
Destinations []GroupMinimum `json:"destinations"`
|
||||
|
||||
// Enabled Policy rule status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Policy rule ID
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Name Policy rule name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// Ports Policy rule affected ports or it ranges list
|
||||
Ports *[]string `json:"ports,omitempty"`
|
||||
|
||||
// Protocol Policy rule type of the traffic
|
||||
Protocol PolicyRuleProtocol `json:"protocol"`
|
||||
|
||||
// Sources Policy rule source groups
|
||||
Sources []GroupMinimum `json:"sources"`
|
||||
}
|
||||
|
||||
// PolicyRuleAction Policy rule accept or drops packets
|
||||
type PolicyRuleAction string
|
||||
|
||||
// PolicyRuleProtocol Policy rule type of the traffic
|
||||
type PolicyRuleProtocol string
|
||||
|
||||
// PolicyRuleMinimum defines model for PolicyRuleMinimum.
|
||||
type PolicyRuleMinimum struct {
|
||||
// Action Policy rule accept or drops packets
|
||||
Action PolicyRuleMinimumAction `json:"action"`
|
||||
|
||||
// Bidirectional Define if the rule is applicable in both directions, sources, and destinations.
|
||||
Bidirectional bool `json:"bidirectional"`
|
||||
|
||||
// Description Policy rule friendly description
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// Enabled Policy rule status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Policy rule ID
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Name Policy rule name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// Ports Policy rule affected ports or it ranges list
|
||||
Ports *[]string `json:"ports,omitempty"`
|
||||
|
||||
// Protocol Policy rule type of the traffic
|
||||
Protocol PolicyRuleMinimumProtocol `json:"protocol"`
|
||||
}
|
||||
|
||||
// PolicyRuleMinimumAction Policy rule accept or drops packets
|
||||
type PolicyRuleMinimumAction string
|
||||
|
||||
// PolicyRuleMinimumProtocol Policy rule type of the traffic
|
||||
type PolicyRuleMinimumProtocol string
|
||||
|
||||
// PolicyRuleUpdate defines model for PolicyRuleUpdate.
|
||||
type PolicyRuleUpdate struct {
|
||||
// Action Policy rule accept or drops packets
|
||||
Action PolicyRuleUpdateAction `json:"action"`
|
||||
|
||||
// Bidirectional Define if the rule is applicable in both directions, sources, and destinations.
|
||||
Bidirectional bool `json:"bidirectional"`
|
||||
|
||||
// Description Policy rule friendly description
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// Destinations Policy rule destination groups
|
||||
Destinations []string `json:"destinations"`
|
||||
|
||||
// Enabled Policy rule status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Policy rule ID
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Name Policy rule name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// Ports Policy rule affected ports or it ranges list
|
||||
Ports *[]string `json:"ports,omitempty"`
|
||||
|
||||
// Protocol Policy rule type of the traffic
|
||||
Protocol PolicyRuleUpdateProtocol `json:"protocol"`
|
||||
|
||||
// Sources Policy rule source groups
|
||||
Sources []string `json:"sources"`
|
||||
}
|
||||
|
||||
// PolicyRuleUpdateAction Policy rule accept or drops packets
|
||||
type PolicyRuleUpdateAction string
|
||||
|
||||
// PolicyRuleUpdateProtocol Policy rule type of the traffic
|
||||
type PolicyRuleUpdateProtocol string
|
||||
|
||||
// PolicyUpdate defines model for PolicyUpdate.
|
||||
type PolicyUpdate struct {
|
||||
// Description Policy friendly description
|
||||
Description string `json:"description"`
|
||||
|
||||
// Enabled Policy status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Policy ID
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Name Policy name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
@@ -371,36 +539,9 @@ type PolicyMinimum struct {
|
||||
Query string `json:"query"`
|
||||
|
||||
// Rules Policy rule object for policy UI editor
|
||||
Rules []PolicyRule `json:"rules"`
|
||||
Rules []PolicyRuleUpdate `json:"rules"`
|
||||
}
|
||||
|
||||
// PolicyRule defines model for PolicyRule.
|
||||
type PolicyRule struct {
|
||||
// Action policy accept or drops packets
|
||||
Action PolicyRuleAction `json:"action"`
|
||||
|
||||
// Description Rule friendly description
|
||||
Description *string `json:"description,omitempty"`
|
||||
|
||||
// Destinations policy destination groups
|
||||
Destinations []GroupMinimum `json:"destinations"`
|
||||
|
||||
// Enabled Rules status
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Rule ID
|
||||
Id *string `json:"id,omitempty"`
|
||||
|
||||
// Name Rule name identifier
|
||||
Name string `json:"name"`
|
||||
|
||||
// Sources policy source groups
|
||||
Sources []GroupMinimum `json:"sources"`
|
||||
}
|
||||
|
||||
// PolicyRuleAction policy accept or drops packets
|
||||
type PolicyRuleAction string
|
||||
|
||||
// Route defines model for Route.
|
||||
type Route struct {
|
||||
// Description Route description
|
||||
@@ -680,10 +821,10 @@ type PutApiGroupsGroupIdJSONRequestBody = GroupRequest
|
||||
type PutApiPeersPeerIdJSONRequestBody = PeerRequest
|
||||
|
||||
// PostApiPoliciesJSONRequestBody defines body for PostApiPolicies for application/json ContentType.
|
||||
type PostApiPoliciesJSONRequestBody = PolicyMinimum
|
||||
type PostApiPoliciesJSONRequestBody = PolicyUpdate
|
||||
|
||||
// PutApiPoliciesPolicyIdJSONRequestBody defines body for PutApiPoliciesPolicyId for application/json ContentType.
|
||||
type PutApiPoliciesPolicyIdJSONRequestBody = PolicyMinimum
|
||||
type PutApiPoliciesPolicyIdJSONRequestBody = PolicyUpdate
|
||||
|
||||
// PostApiRoutesJSONRequestBody defines body for PostApiRoutes for application/json ContentType.
|
||||
type PostApiRoutesJSONRequestBody = RouteRequest
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/xid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
@@ -47,7 +46,17 @@ func (h *Policies) GetAllPolicies(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(w, accountPolicies)
|
||||
policies := []*api.Policy{}
|
||||
for _, policy := range accountPolicies {
|
||||
resp := toPolicyResponse(account, policy)
|
||||
if len(resp.Rules) == 0 {
|
||||
util.WriteError(status.Errorf(status.Internal, "no rules in the policy"), w)
|
||||
return
|
||||
}
|
||||
policies = append(policies, resp)
|
||||
}
|
||||
|
||||
util.WriteJSONObject(w, policies)
|
||||
}
|
||||
|
||||
// UpdatePolicy handles update to a policy identified by a given ID
|
||||
@@ -78,63 +87,7 @@ func (h *Policies) UpdatePolicy(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var req api.PutApiPoliciesPolicyIdJSONRequestBody
|
||||
err = json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name == "" {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "policy name shouldn't be empty"), w)
|
||||
return
|
||||
}
|
||||
|
||||
policy := server.Policy{
|
||||
ID: policyID,
|
||||
Name: req.Name,
|
||||
Enabled: req.Enabled,
|
||||
Description: req.Description,
|
||||
Query: req.Query,
|
||||
}
|
||||
if req.Rules != nil {
|
||||
for _, r := range req.Rules {
|
||||
pr := server.PolicyRule{
|
||||
Destinations: groupMinimumsToStrings(account, r.Destinations),
|
||||
Sources: groupMinimumsToStrings(account, r.Sources),
|
||||
Name: r.Name,
|
||||
}
|
||||
pr.Enabled = r.Enabled
|
||||
if r.Description != nil {
|
||||
pr.Description = *r.Description
|
||||
}
|
||||
if r.Id != nil {
|
||||
pr.ID = *r.Id
|
||||
}
|
||||
switch r.Action {
|
||||
case api.PolicyRuleActionAccept:
|
||||
pr.Action = server.PolicyTrafficActionAccept
|
||||
case api.PolicyRuleActionDrop:
|
||||
pr.Action = server.PolicyTrafficActionDrop
|
||||
default:
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "unknown action type"), w)
|
||||
return
|
||||
}
|
||||
policy.Rules = append(policy.Rules, &pr)
|
||||
}
|
||||
}
|
||||
if err := policy.UpdateQueryFromRules(); err != nil {
|
||||
log.Errorf("failed to update policy query: %v", err)
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
if err = h.accountManager.SavePolicy(account.Id, user.Id, &policy); err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(w, toPolicyResponse(account, &policy))
|
||||
h.savePolicy(w, r, account, user, policyID)
|
||||
}
|
||||
|
||||
// CreatePolicy handles policy creation request
|
||||
@@ -146,9 +99,19 @@ func (h *Policies) CreatePolicy(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var req api.PostApiPoliciesJSONRequestBody
|
||||
err = json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
h.savePolicy(w, r, account, user, "")
|
||||
}
|
||||
|
||||
// savePolicy handles policy creation and update
|
||||
func (h *Policies) savePolicy(
|
||||
w http.ResponseWriter,
|
||||
r *http.Request,
|
||||
account *server.Account,
|
||||
user *server.User,
|
||||
policyID string,
|
||||
) {
|
||||
var req api.PutApiPoliciesPolicyIdJSONRequestBody
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
|
||||
return
|
||||
}
|
||||
@@ -158,49 +121,97 @@ func (h *Policies) CreatePolicy(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
policy := &server.Policy{
|
||||
ID: xid.New().String(),
|
||||
if len(req.Rules) == 0 {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "policy rules shouldn't be empty"), w)
|
||||
return
|
||||
}
|
||||
|
||||
if policyID == "" {
|
||||
policyID = xid.New().String()
|
||||
}
|
||||
|
||||
policy := server.Policy{
|
||||
ID: policyID,
|
||||
Name: req.Name,
|
||||
Enabled: req.Enabled,
|
||||
Description: req.Description,
|
||||
Query: req.Query,
|
||||
}
|
||||
for _, r := range req.Rules {
|
||||
pr := server.PolicyRule{
|
||||
ID: policyID, //TODO: when policy can contain multiple rules, need refactor
|
||||
Name: r.Name,
|
||||
Destinations: groupMinimumsToStrings(account, r.Destinations),
|
||||
Sources: groupMinimumsToStrings(account, r.Sources),
|
||||
Bidirectional: r.Bidirectional,
|
||||
}
|
||||
|
||||
if req.Rules != nil {
|
||||
for _, r := range req.Rules {
|
||||
pr := server.PolicyRule{
|
||||
ID: xid.New().String(),
|
||||
Destinations: groupMinimumsToStrings(account, r.Destinations),
|
||||
Sources: groupMinimumsToStrings(account, r.Sources),
|
||||
Name: r.Name,
|
||||
}
|
||||
pr.Enabled = r.Enabled
|
||||
if r.Description != nil {
|
||||
pr.Description = *r.Description
|
||||
}
|
||||
switch r.Action {
|
||||
case api.PolicyRuleActionAccept:
|
||||
pr.Action = server.PolicyTrafficActionAccept
|
||||
case api.PolicyRuleActionDrop:
|
||||
pr.Action = server.PolicyTrafficActionDrop
|
||||
default:
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "unknown action type"), w)
|
||||
pr.Enabled = r.Enabled
|
||||
if r.Description != nil {
|
||||
pr.Description = *r.Description
|
||||
}
|
||||
|
||||
switch r.Action {
|
||||
case api.PolicyRuleUpdateActionAccept:
|
||||
pr.Action = server.PolicyTrafficActionAccept
|
||||
case api.PolicyRuleUpdateActionDrop:
|
||||
pr.Action = server.PolicyTrafficActionDrop
|
||||
default:
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "unknown action type"), w)
|
||||
return
|
||||
}
|
||||
|
||||
switch r.Protocol {
|
||||
case api.PolicyRuleUpdateProtocolAll:
|
||||
pr.Protocol = server.PolicyRuleProtocolALL
|
||||
case api.PolicyRuleUpdateProtocolTcp:
|
||||
pr.Protocol = server.PolicyRuleProtocolTCP
|
||||
case api.PolicyRuleUpdateProtocolUdp:
|
||||
pr.Protocol = server.PolicyRuleProtocolUDP
|
||||
case api.PolicyRuleUpdateProtocolIcmp:
|
||||
pr.Protocol = server.PolicyRuleProtocolICMP
|
||||
default:
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "unknown protocol type: %v", r.Protocol), w)
|
||||
return
|
||||
}
|
||||
|
||||
if r.Ports != nil && len(*r.Ports) != 0 {
|
||||
ports := *r.Ports
|
||||
pr.Ports = ports[:]
|
||||
}
|
||||
|
||||
// validate policy object
|
||||
switch pr.Protocol {
|
||||
case server.PolicyRuleProtocolALL, server.PolicyRuleProtocolICMP:
|
||||
if len(pr.Ports) != 0 {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "for ALL or ICMP protocol ports is not allowed"), w)
|
||||
return
|
||||
}
|
||||
if !pr.Bidirectional {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "for ALL or ICMP protocol type flow can be only bi-directional"), w)
|
||||
return
|
||||
}
|
||||
case server.PolicyRuleProtocolTCP, server.PolicyRuleProtocolUDP:
|
||||
if !pr.Bidirectional && len(pr.Ports) == 0 {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "for ALL or ICMP protocol type flow can be only bi-directional"), w)
|
||||
return
|
||||
}
|
||||
policy.Rules = append(policy.Rules, &pr)
|
||||
}
|
||||
|
||||
policy.Rules = append(policy.Rules, &pr)
|
||||
}
|
||||
if err := policy.UpdateQueryFromRules(); err != nil {
|
||||
|
||||
if err := h.accountManager.SavePolicy(account.Id, user.Id, &policy); err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
if err = h.accountManager.SavePolicy(account.Id, user.Id, policy); err != nil {
|
||||
util.WriteError(err, w)
|
||||
resp := toPolicyResponse(account, &policy)
|
||||
if len(resp.Rules) == 0 {
|
||||
util.WriteError(status.Errorf(status.Internal, "no rules in the policy"), w)
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(w, toPolicyResponse(account, policy))
|
||||
util.WriteJSONObject(w, resp)
|
||||
}
|
||||
|
||||
// DeletePolicy handles policy deletion request
|
||||
@@ -252,7 +263,13 @@ func (h *Policies) GetPolicy(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(w, toPolicyResponse(account, policy))
|
||||
resp := toPolicyResponse(account, policy)
|
||||
if len(resp.Rules) == 0 {
|
||||
util.WriteError(status.Errorf(status.Internal, "no rules in the policy"), w)
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(w, resp)
|
||||
default:
|
||||
util.WriteError(status.Errorf(status.NotFound, "method not found"), w)
|
||||
}
|
||||
@@ -261,22 +278,24 @@ func (h *Policies) GetPolicy(w http.ResponseWriter, r *http.Request) {
|
||||
func toPolicyResponse(account *server.Account, policy *server.Policy) *api.Policy {
|
||||
cache := make(map[string]api.GroupMinimum)
|
||||
ap := &api.Policy{
|
||||
Id: policy.ID,
|
||||
Id: &policy.ID,
|
||||
Name: policy.Name,
|
||||
Description: policy.Description,
|
||||
Enabled: policy.Enabled,
|
||||
Query: policy.Query,
|
||||
}
|
||||
if len(policy.Rules) == 0 {
|
||||
return ap
|
||||
}
|
||||
|
||||
for _, r := range policy.Rules {
|
||||
rule := api.PolicyRule{
|
||||
Id: &r.ID,
|
||||
Name: r.Name,
|
||||
Enabled: r.Enabled,
|
||||
Description: &r.Description,
|
||||
Id: &r.ID,
|
||||
Name: r.Name,
|
||||
Enabled: r.Enabled,
|
||||
Description: &r.Description,
|
||||
Bidirectional: r.Bidirectional,
|
||||
Protocol: api.PolicyRuleProtocol(r.Protocol),
|
||||
Action: api.PolicyRuleAction(r.Action),
|
||||
}
|
||||
if len(r.Ports) != 0 {
|
||||
portsCopy := r.Ports[:]
|
||||
rule.Ports = &portsCopy
|
||||
}
|
||||
for _, gid := range r.Sources {
|
||||
_, ok := cache[gid]
|
||||
@@ -314,13 +333,13 @@ func toPolicyResponse(account *server.Account, policy *server.Policy) *api.Polic
|
||||
return ap
|
||||
}
|
||||
|
||||
func groupMinimumsToStrings(account *server.Account, gm []api.GroupMinimum) []string {
|
||||
func groupMinimumsToStrings(account *server.Account, gm []string) []string {
|
||||
result := make([]string, 0, len(gm))
|
||||
for _, gm := range gm {
|
||||
if _, ok := account.Groups[gm.Id]; ok {
|
||||
for _, g := range gm {
|
||||
if _, ok := account.Groups[g]; !ok {
|
||||
continue
|
||||
}
|
||||
result = append(result, gm.Id)
|
||||
result = append(result, g)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
315
management/server/http/policies_handler_test.go
Normal file
315
management/server/http/policies_handler_test.go
Normal file
@@ -0,0 +1,315 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
|
||||
"github.com/magiconair/properties/assert"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
)
|
||||
|
||||
func initPoliciesTestData(policies ...*server.Policy) *Policies {
|
||||
testPolicies := make(map[string]*server.Policy, len(policies))
|
||||
for _, policy := range policies {
|
||||
testPolicies[policy.ID] = policy
|
||||
}
|
||||
return &Policies{
|
||||
accountManager: &mock_server.MockAccountManager{
|
||||
GetPolicyFunc: func(_, policyID, _ string) (*server.Policy, error) {
|
||||
policy, ok := testPolicies[policyID]
|
||||
if !ok {
|
||||
return nil, status.Errorf(status.NotFound, "policy not found")
|
||||
}
|
||||
return policy, nil
|
||||
},
|
||||
SavePolicyFunc: func(_, _ string, policy *server.Policy) error {
|
||||
if !strings.HasPrefix(policy.ID, "id-") {
|
||||
policy.ID = "id-was-set"
|
||||
policy.Rules[0].ID = "id-was-set"
|
||||
}
|
||||
return nil
|
||||
},
|
||||
SaveRuleFunc: func(_, _ string, rule *server.Rule) error {
|
||||
if !strings.HasPrefix(rule.ID, "id-") {
|
||||
rule.ID = "id-was-set"
|
||||
}
|
||||
return nil
|
||||
},
|
||||
GetRuleFunc: func(_, ruleID, _ string) (*server.Rule, error) {
|
||||
if ruleID != "idoftherule" {
|
||||
return nil, fmt.Errorf("not found")
|
||||
}
|
||||
return &server.Rule{
|
||||
ID: "idoftherule",
|
||||
Name: "Rule",
|
||||
Source: []string{"idofsrcrule"},
|
||||
Destination: []string{"idofdestrule"},
|
||||
Flow: server.TrafficFlowBidirect,
|
||||
}, nil
|
||||
},
|
||||
GetAccountFromTokenFunc: func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error) {
|
||||
user := server.NewAdminUser("test_user")
|
||||
return &server.Account{
|
||||
Id: claims.AccountId,
|
||||
Domain: "hotmail.com",
|
||||
Policies: []*server.Policy{
|
||||
{ID: "id-existed"},
|
||||
},
|
||||
Groups: map[string]*server.Group{
|
||||
"F": {ID: "F"},
|
||||
"G": {ID: "G"},
|
||||
},
|
||||
Users: map[string]*server.User{
|
||||
"test_user": user,
|
||||
},
|
||||
}, user, nil
|
||||
},
|
||||
},
|
||||
claimsExtractor: jwtclaims.NewClaimsExtractor(
|
||||
jwtclaims.WithFromRequestContext(func(r *http.Request) jwtclaims.AuthorizationClaims {
|
||||
return jwtclaims.AuthorizationClaims{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_id",
|
||||
}
|
||||
}),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoliciesGetPolicy(t *testing.T) {
|
||||
tt := []struct {
|
||||
name string
|
||||
expectedStatus int
|
||||
expectedBody bool
|
||||
requestType string
|
||||
requestPath string
|
||||
requestBody io.Reader
|
||||
}{
|
||||
{
|
||||
name: "GetPolicy OK",
|
||||
expectedBody: true,
|
||||
requestType: http.MethodGet,
|
||||
requestPath: "/api/policies/idofthepolicy",
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "GetPolicy not found",
|
||||
requestType: http.MethodGet,
|
||||
requestPath: "/api/policies/notexists",
|
||||
expectedStatus: http.StatusNotFound,
|
||||
},
|
||||
}
|
||||
|
||||
policy := &server.Policy{
|
||||
ID: "idofthepolicy",
|
||||
Name: "Rule",
|
||||
Rules: []*server.PolicyRule{
|
||||
{ID: "idoftherule", Name: "Rule"},
|
||||
},
|
||||
}
|
||||
|
||||
p := initPoliciesTestData(policy)
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/policies/{policyId}", p.GetPolicy).Methods("GET")
|
||||
router.ServeHTTP(recorder, req)
|
||||
|
||||
res := recorder.Result()
|
||||
defer res.Body.Close()
|
||||
|
||||
if status := recorder.Code; status != tc.expectedStatus {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||
status, tc.expectedStatus)
|
||||
return
|
||||
}
|
||||
|
||||
if !tc.expectedBody {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("I don't know what I expected; %v", err)
|
||||
}
|
||||
|
||||
var got api.Policy
|
||||
if err = json.Unmarshal(content, &got); err != nil {
|
||||
t.Fatalf("Sent content is not in correct json format; %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(t, *got.Id, policy.ID)
|
||||
assert.Equal(t, got.Name, policy.Name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoliciesWritePolicy(t *testing.T) {
|
||||
str := func(s string) *string { return &s }
|
||||
tt := []struct {
|
||||
name string
|
||||
expectedStatus int
|
||||
expectedBody bool
|
||||
expectedPolicy *api.Policy
|
||||
requestType string
|
||||
requestPath string
|
||||
requestBody io.Reader
|
||||
}{
|
||||
{
|
||||
name: "WritePolicy POST OK",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/policies",
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte(`{
|
||||
"Name":"Default POSTed Policy",
|
||||
"Rules":[
|
||||
{
|
||||
"Name":"Default POSTed Policy",
|
||||
"Description": "Description",
|
||||
"Protocol": "tcp",
|
||||
"Action": "accept",
|
||||
"Bidirectional":true
|
||||
}
|
||||
]}`)),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedPolicy: &api.Policy{
|
||||
Id: str("id-was-set"),
|
||||
Name: "Default POSTed Policy",
|
||||
Rules: []api.PolicyRule{
|
||||
{
|
||||
Id: str("id-was-set"),
|
||||
Name: "Default POSTed Policy",
|
||||
Description: str("Description"),
|
||||
Protocol: "tcp",
|
||||
Action: "accept",
|
||||
Bidirectional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WritePolicy POST Invalid Name",
|
||||
requestType: http.MethodPost,
|
||||
requestPath: "/api/policies",
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte(`{"Name":""}`)),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedBody: false,
|
||||
},
|
||||
{
|
||||
name: "WritePolicy PUT OK",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/policies/id-existed",
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte(`{
|
||||
"ID": "id-existed",
|
||||
"Name":"Default POSTed Policy",
|
||||
"Rules":[
|
||||
{
|
||||
"ID": "id-existed",
|
||||
"Name":"Default POSTed Policy",
|
||||
"Description": "Description",
|
||||
"Protocol": "tcp",
|
||||
"Action": "accept",
|
||||
"Bidirectional":true
|
||||
}
|
||||
]}`)),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedBody: true,
|
||||
expectedPolicy: &api.Policy{
|
||||
Id: str("id-existed"),
|
||||
Name: "Default POSTed Policy",
|
||||
Rules: []api.PolicyRule{
|
||||
{
|
||||
Id: str("id-existed"),
|
||||
Name: "Default POSTed Policy",
|
||||
Description: str("Description"),
|
||||
Protocol: "tcp",
|
||||
Action: "accept",
|
||||
Bidirectional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WritePolicy PUT Invalid Name",
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/policies/id-existed",
|
||||
requestBody: bytes.NewBuffer(
|
||||
[]byte(`{"ID":"id-existed","Name":"","Rules":[{"ID":"id-existed"}]}`)),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
},
|
||||
}
|
||||
|
||||
p := initPoliciesTestData(&server.Policy{
|
||||
ID: "id-existed",
|
||||
Name: "Default POSTed Rule",
|
||||
Rules: []*server.PolicyRule{
|
||||
{
|
||||
ID: "id-existed",
|
||||
Name: "Default POSTed Rule",
|
||||
Bidirectional: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/policies", p.CreatePolicy).Methods("POST")
|
||||
router.HandleFunc("/api/policies/{policyId}", p.UpdatePolicy).Methods("PUT")
|
||||
router.ServeHTTP(recorder, req)
|
||||
|
||||
res := recorder.Result()
|
||||
defer res.Body.Close()
|
||||
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("I don't know what I expected; %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if status := recorder.Code; status != tc.expectedStatus {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v, content: %s",
|
||||
status, tc.expectedStatus, string(content))
|
||||
return
|
||||
}
|
||||
|
||||
if !tc.expectedBody {
|
||||
return
|
||||
}
|
||||
|
||||
expected, err := json.Marshal(tc.expectedPolicy)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal expected policy: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, strings.Trim(string(content), " \n"), string(expected), "content mismatch")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -112,10 +112,6 @@ func (h *RulesHandler) UpdateRule(w http.ResponseWriter, r *http.Request) {
|
||||
policy.Rules[0].Destinations = reqDestinations
|
||||
policy.Rules[0].Enabled = !req.Disabled
|
||||
policy.Rules[0].Description = req.Description
|
||||
if err := policy.UpdateQueryFromRules(); err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
switch req.Flow {
|
||||
case server.TrafficFlowBidirectString:
|
||||
|
||||
@@ -30,9 +30,6 @@ func initRulesTestData(rules ...*server.Rule) *RulesHandler {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := policy.UpdateQueryFromRules(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
testPolicies[policy.ID] = policy
|
||||
}
|
||||
return &RulesHandler{
|
||||
|
||||
Reference in New Issue
Block a user