diff --git a/management/server/http/api/openapi.yml b/management/server/http/api/openapi.yml index 5c05c15ad..3de6cf092 100644 --- a/management/server/http/api/openapi.yml +++ b/management/server/http/api/openapi.yml @@ -862,8 +862,8 @@ components: $ref: '#/components/schemas/OSVersionCheck' geo_location_check: $ref: '#/components/schemas/GeoLocationCheck' - private_network_check: - $ref: '#/components/schemas/PrivateNetworkCheck' + peer_network_range_check: + $ref: '#/components/schemas/PeerNetworkRangeCheck' NBVersionCheck: description: Posture check for the version of NetBird type: object @@ -934,16 +934,16 @@ components: required: - locations - action - PrivateNetworkCheck: - description: Posture check for allow or deny private network + PeerNetworkRangeCheck: + description: Posture check for allow or deny access based on peer local network addresses type: object properties: ranges: - description: List of private network ranges in CIDR notation + description: List of peer network ranges in CIDR notation type: array items: type: string - example: ["192.168.1.0/24", "10.0.0.0/8"] + example: ["192.168.1.0/24", "10.0.0.0/8", "2001:db8:1234:1a00::/56"] action: description: Action to take upon policy match type: string diff --git a/management/server/http/api/types.gen.go b/management/server/http/api/types.gen.go index 28fe63c9d..c007663a4 100644 --- a/management/server/http/api/types.gen.go +++ b/management/server/http/api/types.gen.go @@ -74,6 +74,12 @@ const ( NameserverNsTypeUdp NameserverNsType = "udp" ) +// Defines values for PeerNetworkRangeCheckAction. +const ( + PeerNetworkRangeCheckActionAllow PeerNetworkRangeCheckAction = "allow" + PeerNetworkRangeCheckActionDeny PeerNetworkRangeCheckAction = "deny" +) + // Defines values for PolicyRuleAction. const ( PolicyRuleActionAccept PolicyRuleAction = "accept" @@ -116,12 +122,6 @@ const ( PolicyRuleUpdateProtocolUdp PolicyRuleUpdateProtocol = "udp" ) -// Defines values for PrivateNetworkCheckAction. -const ( - PrivateNetworkCheckActionAllow PrivateNetworkCheckAction = "allow" - PrivateNetworkCheckActionDeny PrivateNetworkCheckAction = "deny" -) - // Defines values for UserStatus. const ( UserStatusActive UserStatus = "active" @@ -199,8 +199,8 @@ type Checks struct { // OsVersionCheck Posture check for the version of operating system OsVersionCheck *OSVersionCheck `json:"os_version_check,omitempty"` - // PrivateNetworkCheck Posture check for allow or deny private network - PrivateNetworkCheck *PrivateNetworkCheck `json:"private_network_check,omitempty"` + // PeerNetworkRangeCheck Posture check for allow or deny access based on peer local network addresses + PeerNetworkRangeCheck *PeerNetworkRangeCheck `json:"peer_network_range_check,omitempty"` } // City Describe city geographical location information @@ -656,6 +656,18 @@ type PeerMinimum struct { Name string `json:"name"` } +// PeerNetworkRangeCheck Posture check for allow or deny access based on peer local network addresses +type PeerNetworkRangeCheck struct { + // Action Action to take upon policy match + Action PeerNetworkRangeCheckAction `json:"action"` + + // Ranges List of peer network ranges in CIDR notation + Ranges []string `json:"ranges"` +} + +// PeerNetworkRangeCheckAction Action to take upon policy match +type PeerNetworkRangeCheckAction string + // PeerRequest defines model for PeerRequest. type PeerRequest struct { // ApprovalRequired (Cloud only) Indicates whether peer needs approval @@ -898,18 +910,6 @@ type PostureCheckUpdate struct { Name string `json:"name"` } -// PrivateNetworkCheck Posture check for allow or deny private network -type PrivateNetworkCheck struct { - // Action Action to take upon policy match - Action PrivateNetworkCheckAction `json:"action"` - - // Ranges List of private network ranges in CIDR notation - Ranges []string `json:"ranges"` -} - -// PrivateNetworkCheckAction Action to take upon policy match -type PrivateNetworkCheckAction string - // Route defines model for Route. type Route struct { // Description Route description diff --git a/management/server/http/posture_checks_handler.go b/management/server/http/posture_checks_handler.go index 581bba2b7..fcccc1997 100644 --- a/management/server/http/posture_checks_handler.go +++ b/management/server/http/posture_checks_handler.go @@ -213,8 +213,8 @@ func (p *PostureChecksHandler) savePostureChecks( postureChecks.Checks.GeoLocationCheck = toPostureGeoLocationCheck(geoLocationCheck) } - if privateNetworkCheck := req.Checks.PrivateNetworkCheck; privateNetworkCheck != nil { - postureChecks.Checks.PrivateNetworkCheck, err = toPrivateNetworkCheck(privateNetworkCheck) + if peerNetworkRangeCheck := req.Checks.PeerNetworkRangeCheck; peerNetworkRangeCheck != nil { + postureChecks.Checks.PeerNetworkRangeCheck, err = toPeerNetworkRangeCheck(peerNetworkRangeCheck) if err != nil { util.WriteError(status.Errorf(status.InvalidArgument, "invalid network prefix"), w) return @@ -235,7 +235,7 @@ func validatePostureChecksUpdate(req api.PostureCheckUpdate) error { } if req.Checks == nil || (req.Checks.NbVersionCheck == nil && req.Checks.OsVersionCheck == nil && - req.Checks.GeoLocationCheck == nil && req.Checks.PrivateNetworkCheck == nil) { + req.Checks.GeoLocationCheck == nil && req.Checks.PeerNetworkRangeCheck == nil) { return status.Errorf(status.InvalidArgument, "posture checks shouldn't be empty") } @@ -278,17 +278,17 @@ func validatePostureChecksUpdate(req api.PostureCheckUpdate) error { } } - if privateNetworkCheck := req.Checks.PrivateNetworkCheck; privateNetworkCheck != nil { - if privateNetworkCheck.Action == "" { - return status.Errorf(status.InvalidArgument, "action for private network check shouldn't be empty") + if peerNetworkRangeCheck := req.Checks.PeerNetworkRangeCheck; peerNetworkRangeCheck != nil { + if peerNetworkRangeCheck.Action == "" { + return status.Errorf(status.InvalidArgument, "action for peer network range check shouldn't be empty") } - allowedActions := []api.PrivateNetworkCheckAction{api.PrivateNetworkCheckActionAllow, api.PrivateNetworkCheckActionDeny} - if !slices.Contains(allowedActions, privateNetworkCheck.Action) { - return status.Errorf(status.InvalidArgument, "action for private network check is not valid value") + allowedActions := []api.PeerNetworkRangeCheckAction{api.PeerNetworkRangeCheckActionAllow, api.PeerNetworkRangeCheckActionDeny} + if !slices.Contains(allowedActions, peerNetworkRangeCheck.Action) { + return status.Errorf(status.InvalidArgument, "action for peer network range check is not valid value") } - if len(privateNetworkCheck.Ranges) == 0 { - return status.Errorf(status.InvalidArgument, "network ranges for private network check shouldn't be empty") + if len(peerNetworkRangeCheck.Ranges) == 0 { + return status.Errorf(status.InvalidArgument, "network ranges for peer network range check shouldn't be empty") } } @@ -318,8 +318,8 @@ func toPostureChecksResponse(postureChecks *posture.Checks) *api.PostureCheck { checks.GeoLocationCheck = toGeoLocationCheckResponse(postureChecks.Checks.GeoLocationCheck) } - if postureChecks.Checks.PrivateNetworkCheck != nil { - checks.PrivateNetworkCheck = toPrivateNetworkCheckResponse(postureChecks.Checks.PrivateNetworkCheck) + if postureChecks.Checks.PeerNetworkRangeCheck != nil { + checks.PeerNetworkRangeCheck = toPeerNetworkRangeCheckResponse(postureChecks.Checks.PeerNetworkRangeCheck) } return &api.PostureCheck{ @@ -369,19 +369,19 @@ func toPostureGeoLocationCheck(apiGeoLocationCheck *api.GeoLocationCheck) *postu } } -func toPrivateNetworkCheckResponse(check *posture.PrivateNetworkCheck) *api.PrivateNetworkCheck { +func toPeerNetworkRangeCheckResponse(check *posture.PeerNetworkRangeCheck) *api.PeerNetworkRangeCheck { netPrefixes := make([]string, 0, len(check.Ranges)) for _, netPrefix := range check.Ranges { netPrefixes = append(netPrefixes, netPrefix.String()) } - return &api.PrivateNetworkCheck{ + return &api.PeerNetworkRangeCheck{ Ranges: netPrefixes, - Action: api.PrivateNetworkCheckAction(check.Action), + Action: api.PeerNetworkRangeCheckAction(check.Action), } } -func toPrivateNetworkCheck(check *api.PrivateNetworkCheck) (*posture.PrivateNetworkCheck, error) { +func toPeerNetworkRangeCheck(check *api.PeerNetworkRangeCheck) (*posture.PeerNetworkRangeCheck, error) { prefixes := make([]netip.Prefix, 0) for _, prefix := range check.Ranges { parsedPrefix, err := netip.ParsePrefix(prefix) @@ -391,7 +391,7 @@ func toPrivateNetworkCheck(check *api.PrivateNetworkCheck) (*posture.PrivateNetw prefixes = append(prefixes, parsedPrefix) } - return &posture.PrivateNetworkCheck{ + return &posture.PeerNetworkRangeCheck{ Ranges: prefixes, Action: string(check.Action), }, nil diff --git a/management/server/http/posture_checks_handler_test.go b/management/server/http/posture_checks_handler_test.go index 24a28f3ec..70e803214 100644 --- a/management/server/http/posture_checks_handler_test.go +++ b/management/server/http/posture_checks_handler_test.go @@ -131,7 +131,7 @@ func TestGetPostureCheck(t *testing.T) { ID: "privateNetworkPostureCheck", Name: "privateNetwork", Checks: posture.ChecksDefinition{ - PrivateNetworkCheck: &posture.PrivateNetworkCheck{ + PeerNetworkRangeCheck: &posture.PeerNetworkRangeCheck{ Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/24"), }, @@ -375,7 +375,7 @@ func TestPostureCheckUpdate(t *testing.T) { }, }, { - name: "Create Posture Checks Private Network", + name: "Create Posture Checks Peer Network Range", requestType: http.MethodPost, requestPath: "/api/posture-checks", requestBody: bytes.NewBuffer( @@ -383,7 +383,7 @@ func TestPostureCheckUpdate(t *testing.T) { "name": "default", "description": "default", "checks": { - "private_network_check": { + "peer_network_range_check": { "action": "allow", "ranges": [ "10.0.0.0/8" @@ -398,11 +398,11 @@ func TestPostureCheckUpdate(t *testing.T) { Name: "default", Description: str("default"), Checks: api.Checks{ - PrivateNetworkCheck: &api.PrivateNetworkCheck{ + PeerNetworkRangeCheck: &api.PeerNetworkRangeCheck{ Ranges: []string{ "10.0.0.0/8", }, - Action: api.PrivateNetworkCheckActionAllow, + Action: api.PeerNetworkRangeCheckActionAllow, }, }, }, @@ -715,14 +715,14 @@ func TestPostureCheckUpdate(t *testing.T) { expectedBody: false, }, { - name: "Update Posture Checks Private Network", + name: "Update Posture Checks Peer Network Range", requestType: http.MethodPut, - requestPath: "/api/posture-checks/privateNetworkPostureCheck", + requestPath: "/api/posture-checks/peerNetworkRangePostureCheck", requestBody: bytes.NewBuffer( []byte(`{ "name": "default", "checks": { - "private_network_check": { + "peer_network_range_check": { "action": "deny", "ranges": [ "192.168.1.0/24" @@ -737,11 +737,11 @@ func TestPostureCheckUpdate(t *testing.T) { Name: "default", Description: str(""), Checks: api.Checks{ - PrivateNetworkCheck: &api.PrivateNetworkCheck{ + PeerNetworkRangeCheck: &api.PeerNetworkRangeCheck{ Ranges: []string{ "192.168.1.0/24", }, - Action: api.PrivateNetworkCheckActionDeny, + Action: api.PeerNetworkRangeCheckActionDeny, }, }, }, @@ -784,10 +784,10 @@ func TestPostureCheckUpdate(t *testing.T) { }, }, &posture.Checks{ - ID: "privateNetworkPostureCheck", - Name: "privateNetwork", + ID: "peerNetworkRangePostureCheck", + Name: "peerNetworkRange", Checks: posture.ChecksDefinition{ - PrivateNetworkCheck: &posture.PrivateNetworkCheck{ + PeerNetworkRangeCheck: &posture.PeerNetworkRangeCheck{ Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/24"), }, @@ -891,29 +891,50 @@ func TestPostureCheck_validatePostureChecksUpdate(t *testing.T) { err = validatePostureChecksUpdate(api.PostureCheckUpdate{Name: "Default", Checks: &api.Checks{OsVersionCheck: &osVersionCheck}}) assert.NoError(t, err) - // valid private network check - privateNetworkCheck := api.PrivateNetworkCheck{ - Action: api.PrivateNetworkCheckActionAllow, + // valid peer network range check + peerNetworkRangeCheck := api.PeerNetworkRangeCheck{ + Action: api.PeerNetworkRangeCheckActionAllow, Ranges: []string{ "192.168.1.0/24", "10.0.0.0/8", }, } - err = validatePostureChecksUpdate(api.PostureCheckUpdate{Name: "Default", Checks: &api.Checks{PrivateNetworkCheck: &privateNetworkCheck}}) + err = validatePostureChecksUpdate( + api.PostureCheckUpdate{ + Name: "Default", + Checks: &api.Checks{ + PeerNetworkRangeCheck: &peerNetworkRangeCheck, + }, + }, + ) assert.NoError(t, err) - // invalid private network check - privateNetworkCheck = api.PrivateNetworkCheck{ - Action: api.PrivateNetworkCheckActionDeny, + // invalid peer network range check + peerNetworkRangeCheck = api.PeerNetworkRangeCheck{ + Action: api.PeerNetworkRangeCheckActionDeny, Ranges: []string{}, } - err = validatePostureChecksUpdate(api.PostureCheckUpdate{Name: "Default", Checks: &api.Checks{PrivateNetworkCheck: &privateNetworkCheck}}) + err = validatePostureChecksUpdate( + api.PostureCheckUpdate{ + Name: "Default", + Checks: &api.Checks{ + PeerNetworkRangeCheck: &peerNetworkRangeCheck, + }, + }, + ) assert.Error(t, err) - // invalid private network check - privateNetworkCheck = api.PrivateNetworkCheck{ + // invalid peer network range check + peerNetworkRangeCheck = api.PeerNetworkRangeCheck{ Action: "unknownAction", Ranges: []string{}, } - err = validatePostureChecksUpdate(api.PostureCheckUpdate{Name: "Default", Checks: &api.Checks{PrivateNetworkCheck: &privateNetworkCheck}}) + err = validatePostureChecksUpdate( + api.PostureCheckUpdate{ + Name: "Default", + Checks: &api.Checks{ + PeerNetworkRangeCheck: &peerNetworkRangeCheck, + }, + }, + ) assert.Error(t, err) } diff --git a/management/server/posture/checks.go b/management/server/posture/checks.go index ee85be405..1b1f9d322 100644 --- a/management/server/posture/checks.go +++ b/management/server/posture/checks.go @@ -10,10 +10,10 @@ import ( ) const ( - NBVersionCheckName = "NBVersionCheck" - OSVersionCheckName = "OSVersionCheck" - GeoLocationCheckName = "GeoLocationCheck" - PrivateNetworkCheckName = "PrivateNetworkCheck" + NBVersionCheckName = "NBVersionCheck" + OSVersionCheckName = "OSVersionCheck" + GeoLocationCheckName = "GeoLocationCheck" + PeerNetworkRangeCheckName = "PeerNetworkRangeCheck" CheckActionAllow string = "allow" CheckActionDeny string = "deny" @@ -44,10 +44,10 @@ type Checks struct { // ChecksDefinition contains definition of actual check type ChecksDefinition struct { - NBVersionCheck *NBVersionCheck `json:",omitempty"` - OSVersionCheck *OSVersionCheck `json:",omitempty"` - GeoLocationCheck *GeoLocationCheck `json:",omitempty"` - PrivateNetworkCheck *PrivateNetworkCheck `json:",omitempty"` + NBVersionCheck *NBVersionCheck `json:",omitempty"` + OSVersionCheck *OSVersionCheck `json:",omitempty"` + GeoLocationCheck *GeoLocationCheck `json:",omitempty"` + PeerNetworkRangeCheck *PeerNetworkRangeCheck `json:",omitempty"` } // Copy returns a copy of a checks definition. @@ -85,13 +85,13 @@ func (cd ChecksDefinition) Copy() ChecksDefinition { } copy(cdCopy.GeoLocationCheck.Locations, geoCheck.Locations) } - if cd.PrivateNetworkCheck != nil { - privateNetCheck := cd.PrivateNetworkCheck - cdCopy.PrivateNetworkCheck = &PrivateNetworkCheck{ - Action: privateNetCheck.Action, - Ranges: make([]netip.Prefix, len(privateNetCheck.Ranges)), + if cd.PeerNetworkRangeCheck != nil { + peerNetRangeCheck := cd.PeerNetworkRangeCheck + cdCopy.PeerNetworkRangeCheck = &PeerNetworkRangeCheck{ + Action: peerNetRangeCheck.Action, + Ranges: make([]netip.Prefix, len(peerNetRangeCheck.Ranges)), } - copy(cdCopy.PrivateNetworkCheck.Ranges, privateNetCheck.Ranges) + copy(cdCopy.PeerNetworkRangeCheck.Ranges, peerNetRangeCheck.Ranges) } return cdCopy } @@ -130,8 +130,8 @@ func (pc *Checks) GetChecks() []Check { if pc.Checks.GeoLocationCheck != nil { checks = append(checks, pc.Checks.GeoLocationCheck) } - if pc.Checks.PrivateNetworkCheck != nil { - checks = append(checks, pc.Checks.PrivateNetworkCheck) + if pc.Checks.PeerNetworkRangeCheck != nil { + checks = append(checks, pc.Checks.PeerNetworkRangeCheck) } return checks } diff --git a/management/server/posture/checks_test.go b/management/server/posture/checks_test.go index fc36e7f12..d36d4f50c 100644 --- a/management/server/posture/checks_test.go +++ b/management/server/posture/checks_test.go @@ -254,7 +254,7 @@ func TestChecks_Copy(t *testing.T) { }, Action: CheckActionAllow, }, - PrivateNetworkCheck: &PrivateNetworkCheck{ + PeerNetworkRangeCheck: &PeerNetworkRangeCheck{ Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/24"), netip.MustParsePrefix("10.0.0.0/8"), diff --git a/management/server/posture/network.go b/management/server/posture/network.go index 8607d07aa..9bf969f4c 100644 --- a/management/server/posture/network.go +++ b/management/server/posture/network.go @@ -8,16 +8,16 @@ import ( nbpeer "github.com/netbirdio/netbird/management/server/peer" ) -type PrivateNetworkCheck struct { +type PeerNetworkRangeCheck struct { Action string Ranges []netip.Prefix `gorm:"serializer:json"` } -var _ Check = (*PrivateNetworkCheck)(nil) +var _ Check = (*PeerNetworkRangeCheck)(nil) -func (p *PrivateNetworkCheck) Check(peer nbpeer.Peer) (bool, error) { +func (p *PeerNetworkRangeCheck) Check(peer nbpeer.Peer) (bool, error) { if len(peer.Meta.NetworkAddresses) == 0 { - return false, fmt.Errorf("peer's does not contain private network addresses") + return false, fmt.Errorf("peer's does not contain peer network range addresses") } maskedPrefixes := make([]netip.Prefix, 0, len(p.Ranges)) @@ -34,7 +34,7 @@ func (p *PrivateNetworkCheck) Check(peer nbpeer.Peer) (bool, error) { case CheckActionAllow: return true, nil default: - return false, fmt.Errorf("invalid private network check action: %s", p.Action) + return false, fmt.Errorf("invalid peer network range check action: %s", p.Action) } } } @@ -46,9 +46,9 @@ func (p *PrivateNetworkCheck) Check(peer nbpeer.Peer) (bool, error) { return false, nil } - return false, fmt.Errorf("invalid private network check action: %s", p.Action) + return false, fmt.Errorf("invalid peer network range check action: %s", p.Action) } -func (p *PrivateNetworkCheck) Name() string { - return PrivateNetworkCheckName +func (p *PeerNetworkRangeCheck) Name() string { + return PeerNetworkRangeCheckName } diff --git a/management/server/posture/network_test.go b/management/server/posture/network_test.go index 018005460..36ead4660 100644 --- a/management/server/posture/network_test.go +++ b/management/server/posture/network_test.go @@ -9,17 +9,17 @@ import ( nbpeer "github.com/netbirdio/netbird/management/server/peer" ) -func TestPrivateNetworkCheck_Check(t *testing.T) { +func TestPeerNetworkRangeCheck_Check(t *testing.T) { tests := []struct { name string - check PrivateNetworkCheck + check PeerNetworkRangeCheck peer nbpeer.Peer wantErr bool isValid bool }{ { - name: "Peer private networks matches the allowed range", - check: PrivateNetworkCheck{ + name: "Peer networks range matches the allowed range", + check: PeerNetworkRangeCheck{ Action: CheckActionAllow, Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/24"), @@ -42,8 +42,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) { isValid: true, }, { - name: "Peer private networks doesn't matches the allowed range", - check: PrivateNetworkCheck{ + name: "Peer networks range doesn't matches the allowed range", + check: PeerNetworkRangeCheck{ Action: CheckActionAllow, Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/24"), @@ -63,8 +63,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) { isValid: false, }, { - name: "Peer with no privates network in the allow range", - check: PrivateNetworkCheck{ + name: "Peer with no network range in the allow range", + check: PeerNetworkRangeCheck{ Action: CheckActionAllow, Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/16"), @@ -76,8 +76,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) { isValid: false, }, { - name: "Peer private networks matches the denied range", - check: PrivateNetworkCheck{ + name: "Peer networks range matches the denied range", + check: PeerNetworkRangeCheck{ Action: CheckActionDeny, Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/24"), @@ -100,8 +100,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) { isValid: false, }, { - name: "Peer private networks doesn't matches the denied range", - check: PrivateNetworkCheck{ + name: "Peer networks range doesn't matches the denied range", + check: PeerNetworkRangeCheck{ Action: CheckActionDeny, Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/24"), @@ -121,8 +121,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) { isValid: true, }, { - name: "Peer with no private networks in the denied range", - check: PrivateNetworkCheck{ + name: "Peer with no networks range in the denied range", + check: PeerNetworkRangeCheck{ Action: CheckActionDeny, Ranges: []netip.Prefix{ netip.MustParsePrefix("192.168.0.0/16"),