mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-13 10:21:10 +01:00
Merge pull request #3025 from netbirdio/feature/add-policy-network-resources
[management] Extends policy with source and destination resources
This commit is contained in:
commit
7944b8e843
@ -782,15 +782,18 @@ components:
|
|||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
example: "ch8i4ug6lnn4g9hqv797"
|
example: "ch8i4ug6lnn4g9hqv797"
|
||||||
|
sourceResource:
|
||||||
|
description: Policy rule source resource that the rule is applied to
|
||||||
|
$ref: '#/components/schemas/Resource'
|
||||||
destinations:
|
destinations:
|
||||||
description: Policy rule destination group IDs
|
description: Policy rule destination group IDs
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
example: "ch8i4ug6lnn4g9h7v7m0"
|
example: "ch8i4ug6lnn4g9h7v7m0"
|
||||||
required:
|
destinationResource:
|
||||||
- sources
|
description: Policy rule destination resource that the rule is applied to
|
||||||
- destinations
|
$ref: '#/components/schemas/Resource'
|
||||||
PolicyRule:
|
PolicyRule:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: '#/components/schemas/PolicyRuleMinimum'
|
- $ref: '#/components/schemas/PolicyRuleMinimum'
|
||||||
@ -801,14 +804,17 @@ components:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/GroupMinimum'
|
$ref: '#/components/schemas/GroupMinimum'
|
||||||
|
sourceResource:
|
||||||
|
description: Policy rule source resource that the rule is applied to
|
||||||
|
$ref: '#/components/schemas/Resource'
|
||||||
destinations:
|
destinations:
|
||||||
description: Policy rule destination group IDs
|
description: Policy rule destination group IDs
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/GroupMinimum'
|
$ref: '#/components/schemas/GroupMinimum'
|
||||||
required:
|
destinationResource:
|
||||||
- sources
|
description: Policy rule destination resource that the rule is applied to
|
||||||
- destinations
|
$ref: '#/components/schemas/Resource'
|
||||||
PolicyMinimum:
|
PolicyMinimum:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -1176,6 +1182,24 @@ components:
|
|||||||
- id
|
- id
|
||||||
- network_type
|
- network_type
|
||||||
- $ref: '#/components/schemas/RouteRequest'
|
- $ref: '#/components/schemas/RouteRequest'
|
||||||
|
Resource:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
description: ID of the resource
|
||||||
|
type: string
|
||||||
|
example: chacdk86lnnboviihd7g
|
||||||
|
type:
|
||||||
|
description: Type of the resource
|
||||||
|
$ref: '#/components/schemas/ResourceType'
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- type
|
||||||
|
ResourceType:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/NetworkResourceType'
|
||||||
|
- type: string
|
||||||
|
example: host
|
||||||
NetworkRequest:
|
NetworkRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -1227,14 +1251,16 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
example: chacdk86lnnboviihd7g
|
example: chacdk86lnnboviihd7g
|
||||||
type:
|
type:
|
||||||
description: Network resource type based of the address
|
$ref: '#/components/schemas/NetworkResourceType'
|
||||||
type: string
|
|
||||||
enum: [ "host", "subnet", "domain"]
|
|
||||||
example: host
|
|
||||||
required:
|
required:
|
||||||
- id
|
- id
|
||||||
- type
|
- type
|
||||||
- $ref: '#/components/schemas/NetworkResourceRequest'
|
- $ref: '#/components/schemas/NetworkResourceRequest'
|
||||||
|
NetworkResourceType:
|
||||||
|
description: Network resource type based of the address
|
||||||
|
type: string
|
||||||
|
enum: [ "host", "subnet", "domain" ]
|
||||||
|
example: host
|
||||||
NetworkRouterRequest:
|
NetworkRouterRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -143,6 +143,13 @@ const (
|
|||||||
PolicyRuleUpdateProtocolUdp PolicyRuleUpdateProtocol = "udp"
|
PolicyRuleUpdateProtocolUdp PolicyRuleUpdateProtocol = "udp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Defines values for ResourceType.
|
||||||
|
const (
|
||||||
|
ResourceTypeDomain ResourceType = "domain"
|
||||||
|
ResourceTypeHost ResourceType = "host"
|
||||||
|
ResourceTypeSubnet ResourceType = "subnet"
|
||||||
|
)
|
||||||
|
|
||||||
// Defines values for UserStatus.
|
// Defines values for UserStatus.
|
||||||
const (
|
const (
|
||||||
UserStatusActive UserStatus = "active"
|
UserStatusActive UserStatus = "active"
|
||||||
@ -540,9 +547,6 @@ type NetworkResource struct {
|
|||||||
Type NetworkResourceType `json:"type"`
|
Type NetworkResourceType `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkResourceType Network resource type based of the address
|
|
||||||
type NetworkResourceType string
|
|
||||||
|
|
||||||
// NetworkResourceRequest defines model for NetworkResourceRequest.
|
// NetworkResourceRequest defines model for NetworkResourceRequest.
|
||||||
type NetworkResourceRequest struct {
|
type NetworkResourceRequest struct {
|
||||||
// Address Network resource address (either a direct host like 1.1.1.1 or 1.1.1.1/32, or a subnet like 192.168.178.0/24, or a domain like example.com)
|
// Address Network resource address (either a direct host like 1.1.1.1 or 1.1.1.1/32, or a subnet like 192.168.178.0/24, or a domain like example.com)
|
||||||
@ -555,6 +559,9 @@ type NetworkResourceRequest struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NetworkResourceType Network resource type based of the address
|
||||||
|
type NetworkResourceType string
|
||||||
|
|
||||||
// NetworkRouter defines model for NetworkRouter.
|
// NetworkRouter defines model for NetworkRouter.
|
||||||
type NetworkRouter struct {
|
type NetworkRouter struct {
|
||||||
// Id Network Router Id
|
// Id Network Router Id
|
||||||
@ -873,10 +880,11 @@ type PolicyRule struct {
|
|||||||
Bidirectional bool `json:"bidirectional"`
|
Bidirectional bool `json:"bidirectional"`
|
||||||
|
|
||||||
// Description Policy rule friendly description
|
// Description Policy rule friendly description
|
||||||
Description *string `json:"description,omitempty"`
|
Description *string `json:"description,omitempty"`
|
||||||
|
DestinationResource *Resource `json:"destinationResource,omitempty"`
|
||||||
|
|
||||||
// Destinations Policy rule destination group IDs
|
// Destinations Policy rule destination group IDs
|
||||||
Destinations []GroupMinimum `json:"destinations"`
|
Destinations *[]GroupMinimum `json:"destinations,omitempty"`
|
||||||
|
|
||||||
// Enabled Policy rule status
|
// Enabled Policy rule status
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
@ -894,10 +902,11 @@ type PolicyRule struct {
|
|||||||
Ports *[]string `json:"ports,omitempty"`
|
Ports *[]string `json:"ports,omitempty"`
|
||||||
|
|
||||||
// Protocol Policy rule type of the traffic
|
// Protocol Policy rule type of the traffic
|
||||||
Protocol PolicyRuleProtocol `json:"protocol"`
|
Protocol PolicyRuleProtocol `json:"protocol"`
|
||||||
|
SourceResource *Resource `json:"sourceResource,omitempty"`
|
||||||
|
|
||||||
// Sources Policy rule source group IDs
|
// Sources Policy rule source group IDs
|
||||||
Sources []GroupMinimum `json:"sources"`
|
Sources *[]GroupMinimum `json:"sources,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PolicyRuleAction Policy rule accept or drops packets
|
// PolicyRuleAction Policy rule accept or drops packets
|
||||||
@ -951,10 +960,11 @@ type PolicyRuleUpdate struct {
|
|||||||
Bidirectional bool `json:"bidirectional"`
|
Bidirectional bool `json:"bidirectional"`
|
||||||
|
|
||||||
// Description Policy rule friendly description
|
// Description Policy rule friendly description
|
||||||
Description *string `json:"description,omitempty"`
|
Description *string `json:"description,omitempty"`
|
||||||
|
DestinationResource *Resource `json:"destinationResource,omitempty"`
|
||||||
|
|
||||||
// Destinations Policy rule destination group IDs
|
// Destinations Policy rule destination group IDs
|
||||||
Destinations []string `json:"destinations"`
|
Destinations *[]string `json:"destinations,omitempty"`
|
||||||
|
|
||||||
// Enabled Policy rule status
|
// Enabled Policy rule status
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
@ -972,10 +982,11 @@ type PolicyRuleUpdate struct {
|
|||||||
Ports *[]string `json:"ports,omitempty"`
|
Ports *[]string `json:"ports,omitempty"`
|
||||||
|
|
||||||
// Protocol Policy rule type of the traffic
|
// Protocol Policy rule type of the traffic
|
||||||
Protocol PolicyRuleUpdateProtocol `json:"protocol"`
|
Protocol PolicyRuleUpdateProtocol `json:"protocol"`
|
||||||
|
SourceResource *Resource `json:"sourceResource,omitempty"`
|
||||||
|
|
||||||
// Sources Policy rule source group IDs
|
// Sources Policy rule source group IDs
|
||||||
Sources []string `json:"sources"`
|
Sources *[]string `json:"sources,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PolicyRuleUpdateAction Policy rule accept or drops packets
|
// PolicyRuleUpdateAction Policy rule accept or drops packets
|
||||||
@ -1049,6 +1060,16 @@ type ProcessCheck struct {
|
|||||||
Processes []Process `json:"processes"`
|
Processes []Process `json:"processes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resource defines model for Resource.
|
||||||
|
type Resource struct {
|
||||||
|
// Id Resource ID
|
||||||
|
Id string `json:"id"`
|
||||||
|
Type ResourceType `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceType defines model for ResourceType.
|
||||||
|
type ResourceType string
|
||||||
|
|
||||||
// Route defines model for Route.
|
// Route defines model for Route.
|
||||||
type Route struct {
|
type Route struct {
|
||||||
// AccessControlGroups Access control group identifier associated with route.
|
// AccessControlGroups Access control group identifier associated with route.
|
||||||
|
@ -147,15 +147,56 @@ func (h *handler) savePolicy(w http.ResponseWriter, r *http.Request, accountID s
|
|||||||
ruleID = *rule.Id
|
ruleID = *rule.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasSources := rule.Sources != nil
|
||||||
|
hasSourceResource := rule.SourceResource != nil
|
||||||
|
|
||||||
|
hasDestinations := rule.Destinations != nil
|
||||||
|
hasDestinationResource := rule.DestinationResource != nil
|
||||||
|
|
||||||
|
if hasSources && hasSourceResource {
|
||||||
|
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "specify either sources or source resources, not both"), w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasDestinations && hasDestinationResource {
|
||||||
|
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "specify either destinations or destination resources, not both"), w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(hasSources || hasSourceResource) || !(hasDestinations || hasDestinationResource) {
|
||||||
|
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "specify either sources or source resources and destinations or destination resources"), w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
pr := types.PolicyRule{
|
pr := types.PolicyRule{
|
||||||
ID: ruleID,
|
ID: ruleID,
|
||||||
PolicyID: policyID,
|
PolicyID: policyID,
|
||||||
Name: rule.Name,
|
Name: rule.Name,
|
||||||
Destinations: rule.Destinations,
|
|
||||||
Sources: rule.Sources,
|
|
||||||
Bidirectional: rule.Bidirectional,
|
Bidirectional: rule.Bidirectional,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hasSources {
|
||||||
|
pr.Sources = *rule.Sources
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasSourceResource {
|
||||||
|
// TODO: validate the resource id and type
|
||||||
|
sourceResource := &types.Resource{}
|
||||||
|
sourceResource.FromAPIRequest(rule.SourceResource)
|
||||||
|
pr.SourceResource = *sourceResource
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasDestinations {
|
||||||
|
pr.Destinations = *rule.Destinations
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasDestinationResource {
|
||||||
|
// TODO: validate the resource id and type
|
||||||
|
destinationResource := &types.Resource{}
|
||||||
|
destinationResource.FromAPIRequest(rule.DestinationResource)
|
||||||
|
pr.DestinationResource = *destinationResource
|
||||||
|
}
|
||||||
|
|
||||||
pr.Enabled = rule.Enabled
|
pr.Enabled = rule.Enabled
|
||||||
if rule.Description != nil {
|
if rule.Description != nil {
|
||||||
pr.Description = *rule.Description
|
pr.Description = *rule.Description
|
||||||
@ -338,13 +379,15 @@ func toPolicyResponse(groups []*nbgroup.Group, policy *types.Policy) *api.Policy
|
|||||||
rID := r.ID
|
rID := r.ID
|
||||||
rDescription := r.Description
|
rDescription := r.Description
|
||||||
rule := api.PolicyRule{
|
rule := api.PolicyRule{
|
||||||
Id: &rID,
|
Id: &rID,
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
Enabled: r.Enabled,
|
Enabled: r.Enabled,
|
||||||
Description: &rDescription,
|
Description: &rDescription,
|
||||||
Bidirectional: r.Bidirectional,
|
Bidirectional: r.Bidirectional,
|
||||||
Protocol: api.PolicyRuleProtocol(r.Protocol),
|
Protocol: api.PolicyRuleProtocol(r.Protocol),
|
||||||
Action: api.PolicyRuleAction(r.Action),
|
Action: api.PolicyRuleAction(r.Action),
|
||||||
|
SourceResource: r.SourceResource.ToAPIResponse(),
|
||||||
|
DestinationResource: r.DestinationResource.ToAPIResponse(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.Ports) != 0 {
|
if len(r.Ports) != 0 {
|
||||||
@ -363,26 +406,30 @@ func toPolicyResponse(groups []*nbgroup.Group, policy *types.Policy) *api.Policy
|
|||||||
rule.PortRanges = &portRanges
|
rule.PortRanges = &portRanges
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sources []api.GroupMinimum
|
||||||
for _, gid := range r.Sources {
|
for _, gid := range r.Sources {
|
||||||
_, ok := cache[gid]
|
_, ok := cache[gid]
|
||||||
if ok {
|
if ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if group, ok := groupsMap[gid]; ok {
|
if group, ok := groupsMap[gid]; ok {
|
||||||
minimum := api.GroupMinimum{
|
minimum := api.GroupMinimum{
|
||||||
Id: group.ID,
|
Id: group.ID,
|
||||||
Name: group.Name,
|
Name: group.Name,
|
||||||
PeersCount: len(group.Peers),
|
PeersCount: len(group.Peers),
|
||||||
}
|
}
|
||||||
rule.Sources = append(rule.Sources, minimum)
|
sources = append(sources, minimum)
|
||||||
cache[gid] = minimum
|
cache[gid] = minimum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rule.Sources = &sources
|
||||||
|
|
||||||
|
var destinations []api.GroupMinimum
|
||||||
for _, gid := range r.Destinations {
|
for _, gid := range r.Destinations {
|
||||||
cachedMinimum, ok := cache[gid]
|
cachedMinimum, ok := cache[gid]
|
||||||
if ok {
|
if ok {
|
||||||
rule.Destinations = append(rule.Destinations, cachedMinimum)
|
destinations = append(destinations, cachedMinimum)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if group, ok := groupsMap[gid]; ok {
|
if group, ok := groupsMap[gid]; ok {
|
||||||
@ -391,10 +438,12 @@ func toPolicyResponse(groups []*nbgroup.Group, policy *types.Policy) *api.Policy
|
|||||||
Name: group.Name,
|
Name: group.Name,
|
||||||
PeersCount: len(group.Peers),
|
PeersCount: len(group.Peers),
|
||||||
}
|
}
|
||||||
rule.Destinations = append(rule.Destinations, minimum)
|
destinations = append(destinations, minimum)
|
||||||
cache[gid] = minimum
|
cache[gid] = minimum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rule.Destinations = &destinations
|
||||||
|
|
||||||
ap.Rules = append(ap.Rules, rule)
|
ap.Rules = append(ap.Rules, rule)
|
||||||
}
|
}
|
||||||
return ap
|
return ap
|
||||||
|
@ -177,7 +177,9 @@ func TestPoliciesWritePolicy(t *testing.T) {
|
|||||||
"Description": "Description",
|
"Description": "Description",
|
||||||
"Protocol": "tcp",
|
"Protocol": "tcp",
|
||||||
"Action": "accept",
|
"Action": "accept",
|
||||||
"Bidirectional":true
|
"Bidirectional":true,
|
||||||
|
"Sources": ["F"],
|
||||||
|
"Destinations": ["G"]
|
||||||
}
|
}
|
||||||
]}`)),
|
]}`)),
|
||||||
expectedStatus: http.StatusOK,
|
expectedStatus: http.StatusOK,
|
||||||
@ -193,6 +195,8 @@ func TestPoliciesWritePolicy(t *testing.T) {
|
|||||||
Protocol: "tcp",
|
Protocol: "tcp",
|
||||||
Action: "accept",
|
Action: "accept",
|
||||||
Bidirectional: true,
|
Bidirectional: true,
|
||||||
|
Sources: &[]api.GroupMinimum{{Id: "F"}},
|
||||||
|
Destinations: &[]api.GroupMinimum{{Id: "G"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -221,7 +225,9 @@ func TestPoliciesWritePolicy(t *testing.T) {
|
|||||||
"Description": "Description",
|
"Description": "Description",
|
||||||
"Protocol": "tcp",
|
"Protocol": "tcp",
|
||||||
"Action": "accept",
|
"Action": "accept",
|
||||||
"Bidirectional":true
|
"Bidirectional":true,
|
||||||
|
"Sources": ["F"],
|
||||||
|
"Destinations": ["F"]
|
||||||
}
|
}
|
||||||
]}`)),
|
]}`)),
|
||||||
expectedStatus: http.StatusOK,
|
expectedStatus: http.StatusOK,
|
||||||
@ -237,6 +243,8 @@ func TestPoliciesWritePolicy(t *testing.T) {
|
|||||||
Protocol: "tcp",
|
Protocol: "tcp",
|
||||||
Action: "accept",
|
Action: "accept",
|
||||||
Bidirectional: true,
|
Bidirectional: true,
|
||||||
|
Sources: &[]api.GroupMinimum{{Id: "F"}},
|
||||||
|
Destinations: &[]api.GroupMinimum{{Id: "F"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -41,9 +41,15 @@ type PolicyRule struct {
|
|||||||
// Destinations policy destination groups
|
// Destinations policy destination groups
|
||||||
Destinations []string `gorm:"serializer:json"`
|
Destinations []string `gorm:"serializer:json"`
|
||||||
|
|
||||||
|
// DestinationResource policy destination resource that the rule is applied to
|
||||||
|
DestinationResource Resource `gorm:"serializer:json"`
|
||||||
|
|
||||||
// Sources policy source groups
|
// Sources policy source groups
|
||||||
Sources []string `gorm:"serializer:json"`
|
Sources []string `gorm:"serializer:json"`
|
||||||
|
|
||||||
|
// SourceResource policy source resource that the rule is applied to
|
||||||
|
SourceResource Resource `gorm:"serializer:json"`
|
||||||
|
|
||||||
// Bidirectional define if the rule is applicable in both directions, sources, and destinations
|
// Bidirectional define if the rule is applicable in both directions, sources, and destinations
|
||||||
Bidirectional bool
|
Bidirectional bool
|
||||||
|
|
||||||
|
30
management/server/types/resource.go
Normal file
30
management/server/types/resource.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Resource struct {
|
||||||
|
ID string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resource) ToAPIResponse() *api.Resource {
|
||||||
|
if r.ID == "" && r.Type == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.Resource{
|
||||||
|
Id: r.ID,
|
||||||
|
Type: api.ResourceType(r.Type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resource) FromAPIRequest(req *api.Resource) {
|
||||||
|
if req == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r.ID = req.Id
|
||||||
|
r.Type = string(req.Type)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user