mirror of
https://github.com/netbirdio/netbird.git
synced 2025-06-14 13:56:51 +02:00
Remove deprecated Rules API endpoints (#1523)
This commit is contained in:
parent
042141db06
commit
0b3b50c705
@ -227,9 +227,6 @@ type Account struct {
|
|||||||
PostureChecks []*posture.Checks `gorm:"foreignKey:AccountID;references:id"`
|
PostureChecks []*posture.Checks `gorm:"foreignKey:AccountID;references:id"`
|
||||||
// Settings is a dictionary of Account settings
|
// Settings is a dictionary of Account settings
|
||||||
Settings *Settings `gorm:"embedded;embeddedPrefix:settings_"`
|
Settings *Settings `gorm:"embedded;embeddedPrefix:settings_"`
|
||||||
// deprecated on store and api level
|
|
||||||
Rules map[string]*Rule `json:"-" gorm:"-"`
|
|
||||||
RulesG []Rule `json:"-" gorm:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
|
@ -258,18 +258,6 @@ func TestStore(t *testing.T) {
|
|||||||
t.Errorf("failed to restore a FileStore file - missing Group all")
|
t.Errorf("failed to restore a FileStore file - missing Group all")
|
||||||
}
|
}
|
||||||
|
|
||||||
if restoredAccount.Rules["all"] == nil {
|
|
||||||
t.Errorf("failed to restore a FileStore file - missing Rule all")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if restoredAccount.Rules["dmz"] == nil {
|
|
||||||
t.Errorf("failed to restore a FileStore file - missing Rule dmz")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
assert.Equal(t, account.Rules["all"], restoredAccount.Rules["all"], "failed to restore a FileStore file - missing Rule all")
|
|
||||||
assert.Equal(t, account.Rules["dmz"], restoredAccount.Rules["dmz"], "failed to restore a FileStore file - missing Rule dmz")
|
|
||||||
|
|
||||||
if len(restoredAccount.Policies) != 2 {
|
if len(restoredAccount.Policies) != 2 {
|
||||||
t.Errorf("failed to restore a FileStore file - missing Policies")
|
t.Errorf("failed to restore a FileStore file - missing Policies")
|
||||||
return
|
return
|
||||||
@ -411,7 +399,6 @@ func TestFileStore_GetAccount(t *testing.T) {
|
|||||||
assert.Len(t, account.Peers, len(expected.Peers))
|
assert.Len(t, account.Peers, len(expected.Peers))
|
||||||
assert.Len(t, account.Users, len(expected.Users))
|
assert.Len(t, account.Users, len(expected.Users))
|
||||||
assert.Len(t, account.SetupKeys, len(expected.SetupKeys))
|
assert.Len(t, account.SetupKeys, len(expected.SetupKeys))
|
||||||
assert.Len(t, account.Rules, len(expected.Rules))
|
|
||||||
assert.Len(t, account.Routes, len(expected.Routes))
|
assert.Len(t, account.Routes, len(expected.Routes))
|
||||||
assert.Len(t, account.NameServerGroups, len(expected.NameServerGroups))
|
assert.Len(t, account.NameServerGroups, len(expected.NameServerGroups))
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,6 @@ tags:
|
|||||||
description: Interact with and view information about setup keys.
|
description: Interact with and view information about setup keys.
|
||||||
- name: Groups
|
- name: Groups
|
||||||
description: Interact with and view information about groups.
|
description: Interact with and view information about groups.
|
||||||
- name: Rules
|
|
||||||
description: Interact with and view information about rules.
|
|
||||||
- name: Policies
|
- name: Policies
|
||||||
description: Interact with and view information about policies.
|
description: Interact with and view information about policies.
|
||||||
- name: Posture Checks
|
- name: Posture Checks
|
||||||
@ -621,73 +619,6 @@ components:
|
|||||||
$ref: '#/components/schemas/PeerMinimum'
|
$ref: '#/components/schemas/PeerMinimum'
|
||||||
required:
|
required:
|
||||||
- peers
|
- peers
|
||||||
RuleMinimum:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
description: Rule name identifier
|
|
||||||
type: string
|
|
||||||
example: Default
|
|
||||||
description:
|
|
||||||
description: Rule friendly description
|
|
||||||
type: string
|
|
||||||
example: This is a default rule that allows connections between all the resources
|
|
||||||
disabled:
|
|
||||||
description: Rules status
|
|
||||||
type: boolean
|
|
||||||
example: false
|
|
||||||
flow:
|
|
||||||
description: Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
|
||||||
type: string
|
|
||||||
example: bidirect
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- description
|
|
||||||
- disabled
|
|
||||||
- flow
|
|
||||||
RuleRequest:
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/components/schemas/RuleMinimum'
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
sources:
|
|
||||||
type: array
|
|
||||||
description: List of source group IDs
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
example: "ch8i4ug6lnn4g9hqv7m1"
|
|
||||||
destinations:
|
|
||||||
type: array
|
|
||||||
description: List of destination group IDs
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
example: "ch8i4ug6lnn4g9hqv7m0"
|
|
||||||
Rule:
|
|
||||||
allOf:
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
description: Rule ID
|
|
||||||
type: string
|
|
||||||
example: ch8i4ug6lnn4g9hqv7mg
|
|
||||||
required:
|
|
||||||
- id
|
|
||||||
- $ref: '#/components/schemas/RuleMinimum'
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
sources:
|
|
||||||
description: Rule source group IDs
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/GroupMinimum'
|
|
||||||
destinations:
|
|
||||||
description: Rule destination group IDs
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/GroupMinimum'
|
|
||||||
required:
|
|
||||||
- sources
|
|
||||||
- destinations
|
|
||||||
PolicyRuleMinimum:
|
PolicyRuleMinimum:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -2035,147 +1966,6 @@ paths:
|
|||||||
"$ref": "#/components/responses/forbidden"
|
"$ref": "#/components/responses/forbidden"
|
||||||
'500':
|
'500':
|
||||||
"$ref": "#/components/responses/internal_error"
|
"$ref": "#/components/responses/internal_error"
|
||||||
/api/rules:
|
|
||||||
get:
|
|
||||||
summary: List all Rules
|
|
||||||
description: Returns a list of all rules. This will be deprecated in favour of `/api/policies`.
|
|
||||||
tags: [ Rules ]
|
|
||||||
deprecated: true
|
|
||||||
security:
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
- TokenAuth: [ ]
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: A JSON Array of Rules
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/Rule'
|
|
||||||
'400':
|
|
||||||
"$ref": "#/components/responses/bad_request"
|
|
||||||
'401':
|
|
||||||
"$ref": "#/components/responses/requires_authentication"
|
|
||||||
'403':
|
|
||||||
"$ref": "#/components/responses/forbidden"
|
|
||||||
'500':
|
|
||||||
"$ref": "#/components/responses/internal_error"
|
|
||||||
post:
|
|
||||||
summary: Create a Rule
|
|
||||||
description: Creates a rule. This will be deprecated in favour of `/api/policies`.
|
|
||||||
deprecated: true
|
|
||||||
tags: [ Rules ]
|
|
||||||
security:
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
- TokenAuth: [ ]
|
|
||||||
requestBody:
|
|
||||||
description: New Rule request
|
|
||||||
content:
|
|
||||||
'application/json':
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/RuleRequest'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: A Rule Object
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/Rule'
|
|
||||||
/api/rules/{ruleId}:
|
|
||||||
get:
|
|
||||||
summary: Retrieve a Rule
|
|
||||||
description: Get information about a rules. This will be deprecated in favour of `/api/policies/{policyID}`.
|
|
||||||
deprecated: true
|
|
||||||
tags: [ Rules ]
|
|
||||||
security:
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
- TokenAuth: [ ]
|
|
||||||
parameters:
|
|
||||||
- in: path
|
|
||||||
name: ruleId
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
description: The unique identifier of a rule
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: A Rule object
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/Rule'
|
|
||||||
'400':
|
|
||||||
"$ref": "#/components/responses/bad_request"
|
|
||||||
'401':
|
|
||||||
"$ref": "#/components/responses/requires_authentication"
|
|
||||||
'403':
|
|
||||||
"$ref": "#/components/responses/forbidden"
|
|
||||||
'500':
|
|
||||||
"$ref": "#/components/responses/internal_error"
|
|
||||||
put:
|
|
||||||
summary: Update a Rule
|
|
||||||
description: Update/Replace a rule. This will be deprecated in favour of `/api/policies/{policyID}`.
|
|
||||||
deprecated: true
|
|
||||||
tags: [ Rules ]
|
|
||||||
security:
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
- TokenAuth: [ ]
|
|
||||||
parameters:
|
|
||||||
- in: path
|
|
||||||
name: ruleId
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
description: The unique identifier of a rule
|
|
||||||
requestBody:
|
|
||||||
description: Update Rule request
|
|
||||||
content:
|
|
||||||
'application/json':
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/RuleRequest'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: A Rule object
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/Rule'
|
|
||||||
'400':
|
|
||||||
"$ref": "#/components/responses/bad_request"
|
|
||||||
'401':
|
|
||||||
"$ref": "#/components/responses/requires_authentication"
|
|
||||||
'403':
|
|
||||||
"$ref": "#/components/responses/forbidden"
|
|
||||||
'500':
|
|
||||||
"$ref": "#/components/responses/internal_error"
|
|
||||||
delete:
|
|
||||||
summary: Delete a Rule
|
|
||||||
description: Delete a rule. This will be deprecated in favour of `/api/policies/{policyID}`.
|
|
||||||
deprecated: true
|
|
||||||
tags: [ Rules ]
|
|
||||||
security:
|
|
||||||
- BearerAuth: [ ]
|
|
||||||
- TokenAuth: [ ]
|
|
||||||
parameters:
|
|
||||||
- in: path
|
|
||||||
name: ruleId
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
description: The unique identifier of a rule
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Delete status code
|
|
||||||
content: { }
|
|
||||||
'400':
|
|
||||||
"$ref": "#/components/responses/bad_request"
|
|
||||||
'401':
|
|
||||||
"$ref": "#/components/responses/requires_authentication"
|
|
||||||
'403':
|
|
||||||
"$ref": "#/components/responses/forbidden"
|
|
||||||
'500':
|
|
||||||
"$ref": "#/components/responses/internal_error"
|
|
||||||
/api/policies:
|
/api/policies:
|
||||||
get:
|
get:
|
||||||
summary: List all Policies
|
summary: List all Policies
|
||||||
|
@ -976,66 +976,6 @@ type RouteRequest struct {
|
|||||||
PeerGroups *[]string `json:"peer_groups,omitempty"`
|
PeerGroups *[]string `json:"peer_groups,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rule defines model for Rule.
|
|
||||||
type Rule struct {
|
|
||||||
// Description Rule friendly description
|
|
||||||
Description string `json:"description"`
|
|
||||||
|
|
||||||
// Destinations Rule destination group IDs
|
|
||||||
Destinations []GroupMinimum `json:"destinations"`
|
|
||||||
|
|
||||||
// Disabled Rules status
|
|
||||||
Disabled bool `json:"disabled"`
|
|
||||||
|
|
||||||
// Flow Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
|
||||||
Flow string `json:"flow"`
|
|
||||||
|
|
||||||
// Id Rule ID
|
|
||||||
Id string `json:"id"`
|
|
||||||
|
|
||||||
// Name Rule name identifier
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// Sources Rule source group IDs
|
|
||||||
Sources []GroupMinimum `json:"sources"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RuleMinimum defines model for RuleMinimum.
|
|
||||||
type RuleMinimum struct {
|
|
||||||
// Description Rule friendly description
|
|
||||||
Description string `json:"description"`
|
|
||||||
|
|
||||||
// Disabled Rules status
|
|
||||||
Disabled bool `json:"disabled"`
|
|
||||||
|
|
||||||
// Flow Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
|
||||||
Flow string `json:"flow"`
|
|
||||||
|
|
||||||
// Name Rule name identifier
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RuleRequest defines model for RuleRequest.
|
|
||||||
type RuleRequest struct {
|
|
||||||
// Description Rule friendly description
|
|
||||||
Description string `json:"description"`
|
|
||||||
|
|
||||||
// Destinations List of destination group IDs
|
|
||||||
Destinations *[]string `json:"destinations,omitempty"`
|
|
||||||
|
|
||||||
// Disabled Rules status
|
|
||||||
Disabled bool `json:"disabled"`
|
|
||||||
|
|
||||||
// Flow Rule flow, currently, only "bidirect" for bi-directional traffic is accepted
|
|
||||||
Flow string `json:"flow"`
|
|
||||||
|
|
||||||
// Name Rule name identifier
|
|
||||||
Name string `json:"name"`
|
|
||||||
|
|
||||||
// Sources List of source group IDs
|
|
||||||
Sources *[]string `json:"sources,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetupKey defines model for SetupKey.
|
// SetupKey defines model for SetupKey.
|
||||||
type SetupKey struct {
|
type SetupKey struct {
|
||||||
// AutoGroups List of group IDs to auto-assign to peers registered with this key
|
// AutoGroups List of group IDs to auto-assign to peers registered with this key
|
||||||
@ -1219,12 +1159,6 @@ type PostApiRoutesJSONRequestBody = RouteRequest
|
|||||||
// PutApiRoutesRouteIdJSONRequestBody defines body for PutApiRoutesRouteId for application/json ContentType.
|
// PutApiRoutesRouteIdJSONRequestBody defines body for PutApiRoutesRouteId for application/json ContentType.
|
||||||
type PutApiRoutesRouteIdJSONRequestBody = RouteRequest
|
type PutApiRoutesRouteIdJSONRequestBody = RouteRequest
|
||||||
|
|
||||||
// PostApiRulesJSONRequestBody defines body for PostApiRules for application/json ContentType.
|
|
||||||
type PostApiRulesJSONRequestBody = RuleRequest
|
|
||||||
|
|
||||||
// PutApiRulesRuleIdJSONRequestBody defines body for PutApiRulesRuleId for application/json ContentType.
|
|
||||||
type PutApiRulesRuleIdJSONRequestBody = RuleRequest
|
|
||||||
|
|
||||||
// PostApiSetupKeysJSONRequestBody defines body for PostApiSetupKeys for application/json ContentType.
|
// PostApiSetupKeysJSONRequestBody defines body for PostApiSetupKeys for application/json ContentType.
|
||||||
type PostApiSetupKeysJSONRequestBody = SetupKeyRequest
|
type PostApiSetupKeysJSONRequestBody = SetupKeyRequest
|
||||||
|
|
||||||
|
@ -85,7 +85,6 @@ func APIHandler(ctx context.Context, accountManager s.AccountManager, LocationMa
|
|||||||
api.addUsersEndpoint()
|
api.addUsersEndpoint()
|
||||||
api.addUsersTokensEndpoint()
|
api.addUsersTokensEndpoint()
|
||||||
api.addSetupKeysEndpoint()
|
api.addSetupKeysEndpoint()
|
||||||
api.addRulesEndpoint()
|
|
||||||
api.addPoliciesEndpoint()
|
api.addPoliciesEndpoint()
|
||||||
api.addGroupsEndpoint()
|
api.addGroupsEndpoint()
|
||||||
api.addRoutesEndpoint()
|
api.addRoutesEndpoint()
|
||||||
@ -158,15 +157,6 @@ func (apiHandler *apiHandler) addSetupKeysEndpoint() {
|
|||||||
apiHandler.Router.HandleFunc("/setup-keys/{keyId}", keysHandler.UpdateSetupKey).Methods("PUT", "OPTIONS")
|
apiHandler.Router.HandleFunc("/setup-keys/{keyId}", keysHandler.UpdateSetupKey).Methods("PUT", "OPTIONS")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (apiHandler *apiHandler) addRulesEndpoint() {
|
|
||||||
rulesHandler := NewRulesHandler(apiHandler.AccountManager, apiHandler.AuthCfg)
|
|
||||||
apiHandler.Router.HandleFunc("/rules", rulesHandler.GetAllRules).Methods("GET", "OPTIONS")
|
|
||||||
apiHandler.Router.HandleFunc("/rules", rulesHandler.CreateRule).Methods("POST", "OPTIONS")
|
|
||||||
apiHandler.Router.HandleFunc("/rules/{ruleId}", rulesHandler.UpdateRule).Methods("PUT", "OPTIONS")
|
|
||||||
apiHandler.Router.HandleFunc("/rules/{ruleId}", rulesHandler.GetRule).Methods("GET", "OPTIONS")
|
|
||||||
apiHandler.Router.HandleFunc("/rules/{ruleId}", rulesHandler.DeleteRule).Methods("DELETE", "OPTIONS")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (apiHandler *apiHandler) addPoliciesEndpoint() {
|
func (apiHandler *apiHandler) addPoliciesEndpoint() {
|
||||||
policiesHandler := NewPoliciesHandler(apiHandler.AccountManager, apiHandler.AuthCfg)
|
policiesHandler := NewPoliciesHandler(apiHandler.AccountManager, apiHandler.AuthCfg)
|
||||||
apiHandler.Router.HandleFunc("/policies", policiesHandler.GetAllPolicies).Methods("GET", "OPTIONS")
|
apiHandler.Router.HandleFunc("/policies", policiesHandler.GetAllPolicies).Methods("GET", "OPTIONS")
|
||||||
|
@ -3,7 +3,6 @@ package http
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@ -44,24 +43,6 @@ func initPoliciesTestData(policies ...*server.Policy) *Policies {
|
|||||||
}
|
}
|
||||||
return nil
|
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) {
|
GetAccountFromTokenFunc: func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error) {
|
||||||
user := server.NewAdminUser("test_user")
|
user := server.NewAdminUser("test_user")
|
||||||
return &server.Account{
|
return &server.Account{
|
||||||
|
@ -1,305 +0,0 @@
|
|||||||
package http
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/rs/xid"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
|
||||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RulesHandler is a handler that returns rules of the account
|
|
||||||
type RulesHandler struct {
|
|
||||||
accountManager server.AccountManager
|
|
||||||
claimsExtractor *jwtclaims.ClaimsExtractor
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRulesHandler creates a new RulesHandler HTTP handler
|
|
||||||
func NewRulesHandler(accountManager server.AccountManager, authCfg AuthCfg) *RulesHandler {
|
|
||||||
return &RulesHandler{
|
|
||||||
accountManager: accountManager,
|
|
||||||
claimsExtractor: jwtclaims.NewClaimsExtractor(
|
|
||||||
jwtclaims.WithAudience(authCfg.Audience),
|
|
||||||
jwtclaims.WithUserIDClaim(authCfg.UserIDClaim),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAllRules list for the account
|
|
||||||
func (h *RulesHandler) GetAllRules(w http.ResponseWriter, r *http.Request) {
|
|
||||||
claims := h.claimsExtractor.FromRequestContext(r)
|
|
||||||
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
accountPolicies, err := h.accountManager.ListPolicies(account.Id, user.Id)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rules := []*api.Rule{}
|
|
||||||
for _, policy := range accountPolicies {
|
|
||||||
for _, r := range policy.Rules {
|
|
||||||
rules = append(rules, toRuleResponse(account, r.ToRule()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
util.WriteJSONObject(w, rules)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateRule handles update to a rule identified by a given ID
|
|
||||||
func (h *RulesHandler) UpdateRule(w http.ResponseWriter, r *http.Request) {
|
|
||||||
claims := h.claimsExtractor.FromRequestContext(r)
|
|
||||||
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
|
||||||
ruleID := vars["ruleId"]
|
|
||||||
if len(ruleID) == 0 {
|
|
||||||
util.WriteError(status.Errorf(status.InvalidArgument, "invalid rule ID"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
policy, err := h.accountManager.GetPolicy(account.Id, ruleID, user.Id)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var req api.PutApiRulesRuleIdJSONRequestBody
|
|
||||||
err = json.NewDecoder(r.Body).Decode(&req)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Name == "" {
|
|
||||||
util.WriteError(status.Errorf(status.InvalidArgument, "rule name shouldn't be empty"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var reqSources []string
|
|
||||||
if req.Sources != nil {
|
|
||||||
reqSources = *req.Sources
|
|
||||||
}
|
|
||||||
|
|
||||||
var reqDestinations []string
|
|
||||||
if req.Destinations != nil {
|
|
||||||
reqDestinations = *req.Destinations
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(policy.Rules) != 1 {
|
|
||||||
util.WriteError(status.Errorf(status.Internal, "policy should contain exactly one rule"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
policy.Name = req.Name
|
|
||||||
policy.Description = req.Description
|
|
||||||
policy.Enabled = !req.Disabled
|
|
||||||
policy.Rules[0].ID = ruleID
|
|
||||||
policy.Rules[0].Name = req.Name
|
|
||||||
policy.Rules[0].Sources = reqSources
|
|
||||||
policy.Rules[0].Destinations = reqDestinations
|
|
||||||
policy.Rules[0].Enabled = !req.Disabled
|
|
||||||
policy.Rules[0].Description = req.Description
|
|
||||||
|
|
||||||
switch req.Flow {
|
|
||||||
case server.TrafficFlowBidirectString:
|
|
||||||
policy.Rules[0].Action = server.PolicyTrafficActionAccept
|
|
||||||
default:
|
|
||||||
util.WriteError(status.Errorf(status.InvalidArgument, "unknown flow type"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = h.accountManager.SavePolicy(account.Id, user.Id, policy)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := toRuleResponse(account, policy.Rules[0].ToRule())
|
|
||||||
|
|
||||||
util.WriteJSONObject(w, &resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRule handles rule creation request
|
|
||||||
func (h *RulesHandler) CreateRule(w http.ResponseWriter, r *http.Request) {
|
|
||||||
claims := h.claimsExtractor.FromRequestContext(r)
|
|
||||||
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var req api.PostApiRulesJSONRequestBody
|
|
||||||
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, "rule name shouldn't be empty"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var reqSources []string
|
|
||||||
if req.Sources != nil {
|
|
||||||
reqSources = *req.Sources
|
|
||||||
}
|
|
||||||
|
|
||||||
var reqDestinations []string
|
|
||||||
if req.Destinations != nil {
|
|
||||||
reqDestinations = *req.Destinations
|
|
||||||
}
|
|
||||||
|
|
||||||
rule := server.Rule{
|
|
||||||
ID: xid.New().String(),
|
|
||||||
Name: req.Name,
|
|
||||||
Source: reqSources,
|
|
||||||
Destination: reqDestinations,
|
|
||||||
Disabled: req.Disabled,
|
|
||||||
Description: req.Description,
|
|
||||||
}
|
|
||||||
|
|
||||||
switch req.Flow {
|
|
||||||
case server.TrafficFlowBidirectString:
|
|
||||||
rule.Flow = server.TrafficFlowBidirect
|
|
||||||
default:
|
|
||||||
util.WriteError(status.Errorf(status.InvalidArgument, "unknown flow type"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
policy, err := server.RuleToPolicy(&rule)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = h.accountManager.SavePolicy(account.Id, user.Id, policy)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := toRuleResponse(account, &rule)
|
|
||||||
|
|
||||||
util.WriteJSONObject(w, &resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRule handles rule deletion request
|
|
||||||
func (h *RulesHandler) DeleteRule(w http.ResponseWriter, r *http.Request) {
|
|
||||||
claims := h.claimsExtractor.FromRequestContext(r)
|
|
||||||
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
aID := account.Id
|
|
||||||
|
|
||||||
rID := mux.Vars(r)["ruleId"]
|
|
||||||
if len(rID) == 0 {
|
|
||||||
util.WriteError(status.Errorf(status.InvalidArgument, "invalid rule ID"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = h.accountManager.DeletePolicy(aID, rID, user.Id)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
util.WriteJSONObject(w, emptyObject{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRule handles a group Get request identified by ID
|
|
||||||
func (h *RulesHandler) GetRule(w http.ResponseWriter, r *http.Request) {
|
|
||||||
claims := h.claimsExtractor.FromRequestContext(r)
|
|
||||||
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch r.Method {
|
|
||||||
case http.MethodGet:
|
|
||||||
ruleID := mux.Vars(r)["ruleId"]
|
|
||||||
if len(ruleID) == 0 {
|
|
||||||
util.WriteError(status.Errorf(status.InvalidArgument, "invalid rule ID"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
policy, err := h.accountManager.GetPolicy(account.Id, ruleID, user.Id)
|
|
||||||
if err != nil {
|
|
||||||
util.WriteError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
util.WriteJSONObject(w, toRuleResponse(account, policy.Rules[0].ToRule()))
|
|
||||||
default:
|
|
||||||
util.WriteError(status.Errorf(status.NotFound, "method not found"), w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toRuleResponse(account *server.Account, rule *server.Rule) *api.Rule {
|
|
||||||
cache := make(map[string]api.GroupMinimum)
|
|
||||||
gr := api.Rule{
|
|
||||||
Id: rule.ID,
|
|
||||||
Name: rule.Name,
|
|
||||||
Description: rule.Description,
|
|
||||||
Disabled: rule.Disabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
switch rule.Flow {
|
|
||||||
case server.TrafficFlowBidirect:
|
|
||||||
gr.Flow = server.TrafficFlowBidirectString
|
|
||||||
default:
|
|
||||||
gr.Flow = "unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, gid := range rule.Source {
|
|
||||||
_, ok := cache[gid]
|
|
||||||
if ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if group, ok := account.Groups[gid]; ok {
|
|
||||||
minimum := api.GroupMinimum{
|
|
||||||
Id: group.ID,
|
|
||||||
Name: group.Name,
|
|
||||||
PeersCount: len(group.Peers),
|
|
||||||
}
|
|
||||||
|
|
||||||
gr.Sources = append(gr.Sources, minimum)
|
|
||||||
cache[gid] = minimum
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, gid := range rule.Destination {
|
|
||||||
cachedMinimum, ok := cache[gid]
|
|
||||||
if ok {
|
|
||||||
gr.Destinations = append(gr.Destinations, cachedMinimum)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if group, ok := account.Groups[gid]; ok {
|
|
||||||
minimum := api.GroupMinimum{
|
|
||||||
Id: group.ID,
|
|
||||||
Name: group.Name,
|
|
||||||
PeersCount: len(group.Peers),
|
|
||||||
}
|
|
||||||
gr.Destinations = append(gr.Destinations, minimum)
|
|
||||||
cache[gid] = minimum
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &gr
|
|
||||||
}
|
|
@ -1,265 +0,0 @@
|
|||||||
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 initRulesTestData(rules ...*server.Rule) *RulesHandler {
|
|
||||||
testPolicies := make(map[string]*server.Policy, len(rules))
|
|
||||||
for _, rule := range rules {
|
|
||||||
policy, err := server.RuleToPolicy(rule)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
testPolicies[policy.ID] = policy
|
|
||||||
}
|
|
||||||
return &RulesHandler{
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
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",
|
|
||||||
Rules: map[string]*server.Rule{"id-existed": {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 TestRulesGetRule(t *testing.T) {
|
|
||||||
tt := []struct {
|
|
||||||
name string
|
|
||||||
expectedStatus int
|
|
||||||
expectedBody bool
|
|
||||||
requestType string
|
|
||||||
requestPath string
|
|
||||||
requestBody io.Reader
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "GetRule OK",
|
|
||||||
expectedBody: true,
|
|
||||||
requestType: http.MethodGet,
|
|
||||||
requestPath: "/api/rules/idoftherule",
|
|
||||||
expectedStatus: http.StatusOK,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "GetRule not found",
|
|
||||||
requestType: http.MethodGet,
|
|
||||||
requestPath: "/api/rules/notexists",
|
|
||||||
expectedStatus: http.StatusNotFound,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
rule := &server.Rule{
|
|
||||||
ID: "idoftherule",
|
|
||||||
Name: "Rule",
|
|
||||||
}
|
|
||||||
|
|
||||||
p := initRulesTestData(rule)
|
|
||||||
|
|
||||||
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/rules/{ruleId}", p.GetRule).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.Rule
|
|
||||||
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, rule.ID)
|
|
||||||
assert.Equal(t, got.Name, rule.Name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRulesWriteRule(t *testing.T) {
|
|
||||||
tt := []struct {
|
|
||||||
name string
|
|
||||||
expectedStatus int
|
|
||||||
expectedBody bool
|
|
||||||
expectedRule *api.Rule
|
|
||||||
requestType string
|
|
||||||
requestPath string
|
|
||||||
requestBody io.Reader
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "WriteRule POST OK",
|
|
||||||
requestType: http.MethodPost,
|
|
||||||
requestPath: "/api/rules",
|
|
||||||
requestBody: bytes.NewBuffer(
|
|
||||||
[]byte(`{"Name":"Default POSTed Rule","Flow":"bidirect"}`)),
|
|
||||||
expectedStatus: http.StatusOK,
|
|
||||||
expectedBody: true,
|
|
||||||
expectedRule: &api.Rule{
|
|
||||||
Id: "id-was-set",
|
|
||||||
Name: "Default POSTed Rule",
|
|
||||||
Flow: server.TrafficFlowBidirectString,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "WriteRule POST Invalid Name",
|
|
||||||
requestType: http.MethodPost,
|
|
||||||
requestPath: "/api/rules",
|
|
||||||
requestBody: bytes.NewBuffer(
|
|
||||||
[]byte(`{"Name":"","Flow":"bidirect"}`)),
|
|
||||||
expectedStatus: http.StatusUnprocessableEntity,
|
|
||||||
expectedBody: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "WriteRule PUT OK",
|
|
||||||
requestType: http.MethodPut,
|
|
||||||
requestPath: "/api/rules/id-existed",
|
|
||||||
requestBody: bytes.NewBuffer(
|
|
||||||
[]byte(`{"Name":"Default POSTed Rule","Flow":"bidirect"}`)),
|
|
||||||
expectedStatus: http.StatusOK,
|
|
||||||
expectedBody: true,
|
|
||||||
expectedRule: &api.Rule{
|
|
||||||
Id: "id-existed",
|
|
||||||
Name: "Default POSTed Rule",
|
|
||||||
Flow: server.TrafficFlowBidirectString,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "WriteRule PUT Invalid Name",
|
|
||||||
requestType: http.MethodPut,
|
|
||||||
requestPath: "/api/rules/id-existed",
|
|
||||||
requestBody: bytes.NewBuffer(
|
|
||||||
[]byte(`{"Name":"","Flow":"bidirect"}`)),
|
|
||||||
expectedStatus: http.StatusUnprocessableEntity,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
p := initRulesTestData(&server.Rule{
|
|
||||||
ID: "id-existed",
|
|
||||||
Name: "Default POSTed Rule",
|
|
||||||
Flow: server.TrafficFlowBidirect,
|
|
||||||
})
|
|
||||||
|
|
||||||
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/rules", p.CreateRule).Methods("POST")
|
|
||||||
router.HandleFunc("/api/rules/{ruleId}", p.UpdateRule).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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
got := &api.Rule{}
|
|
||||||
if err = json.Unmarshal(content, &got); err != nil {
|
|
||||||
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
||||||
}
|
|
||||||
tc.expectedRule.Id = got.Id
|
|
||||||
|
|
||||||
assert.Equal(t, got, tc.expectedRule)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -38,10 +38,7 @@ type MockAccountManager struct {
|
|||||||
ListGroupsFunc func(accountID string) ([]*server.Group, error)
|
ListGroupsFunc func(accountID string) ([]*server.Group, error)
|
||||||
GroupAddPeerFunc func(accountID, groupID, peerID string) error
|
GroupAddPeerFunc func(accountID, groupID, peerID string) error
|
||||||
GroupDeletePeerFunc func(accountID, groupID, peerID string) error
|
GroupDeletePeerFunc func(accountID, groupID, peerID string) error
|
||||||
GetRuleFunc func(accountID, ruleID, userID string) (*server.Rule, error)
|
|
||||||
SaveRuleFunc func(accountID, userID string, rule *server.Rule) error
|
|
||||||
DeleteRuleFunc func(accountID, ruleID, userID string) error
|
DeleteRuleFunc func(accountID, ruleID, userID string) error
|
||||||
ListRulesFunc func(accountID, userID string) ([]*server.Rule, error)
|
|
||||||
GetPolicyFunc func(accountID, policyID, userID string) (*server.Policy, error)
|
GetPolicyFunc func(accountID, policyID, userID string) (*server.Policy, error)
|
||||||
SavePolicyFunc func(accountID, userID string, policy *server.Policy) error
|
SavePolicyFunc func(accountID, userID string, policy *server.Policy) error
|
||||||
DeletePolicyFunc func(accountID, policyID, userID string) error
|
DeletePolicyFunc func(accountID, policyID, userID string) error
|
||||||
@ -302,22 +299,6 @@ func (am *MockAccountManager) GroupDeletePeer(accountID, groupID, peerID string)
|
|||||||
return status.Errorf(codes.Unimplemented, "method GroupDeletePeer is not implemented")
|
return status.Errorf(codes.Unimplemented, "method GroupDeletePeer is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRule mock implementation of GetRule from server.AccountManager interface
|
|
||||||
func (am *MockAccountManager) GetRule(accountID, ruleID, userID string) (*server.Rule, error) {
|
|
||||||
if am.GetRuleFunc != nil {
|
|
||||||
return am.GetRuleFunc(accountID, ruleID, userID)
|
|
||||||
}
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetRule is not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// SaveRule mock implementation of SaveRule from server.AccountManager interface
|
|
||||||
func (am *MockAccountManager) SaveRule(accountID, userID string, rule *server.Rule) error {
|
|
||||||
if am.SaveRuleFunc != nil {
|
|
||||||
return am.SaveRuleFunc(accountID, userID, rule)
|
|
||||||
}
|
|
||||||
return status.Errorf(codes.Unimplemented, "method SaveRule is not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRule mock implementation of DeleteRule from server.AccountManager interface
|
// DeleteRule mock implementation of DeleteRule from server.AccountManager interface
|
||||||
func (am *MockAccountManager) DeleteRule(accountID, ruleID, userID string) error {
|
func (am *MockAccountManager) DeleteRule(accountID, ruleID, userID string) error {
|
||||||
if am.DeleteRuleFunc != nil {
|
if am.DeleteRuleFunc != nil {
|
||||||
@ -326,14 +307,6 @@ func (am *MockAccountManager) DeleteRule(accountID, ruleID, userID string) error
|
|||||||
return status.Errorf(codes.Unimplemented, "method DeleteRule is not implemented")
|
return status.Errorf(codes.Unimplemented, "method DeleteRule is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListRules mock implementation of ListRules from server.AccountManager interface
|
|
||||||
func (am *MockAccountManager) ListRules(accountID, userID string) ([]*server.Rule, error) {
|
|
||||||
if am.ListRulesFunc != nil {
|
|
||||||
return am.ListRulesFunc(accountID, userID)
|
|
||||||
}
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ListRules is not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPolicy mock implementation of GetPolicy from server.AccountManager interface
|
// GetPolicy mock implementation of GetPolicy from server.AccountManager interface
|
||||||
func (am *MockAccountManager) GetPolicy(accountID, policyID, userID string) (*server.Policy, error) {
|
func (am *MockAccountManager) GetPolicy(accountID, policyID, userID string) (*server.Policy, error) {
|
||||||
if am.GetPolicyFunc != nil {
|
if am.GetPolicyFunc != nil {
|
||||||
|
@ -52,6 +52,17 @@ const (
|
|||||||
PolicyRuleFlowBidirect = PolicyRuleDirection("bidirect")
|
PolicyRuleFlowBidirect = PolicyRuleDirection("bidirect")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultRuleName is a name for the Default rule that is created for every account
|
||||||
|
DefaultRuleName = "Default"
|
||||||
|
// DefaultRuleDescription is a description for the Default rule that is created for every account
|
||||||
|
DefaultRuleDescription = "This is a default rule that allows connections between all the resources"
|
||||||
|
// DefaultPolicyName is a name for the Default policy that is created for every account
|
||||||
|
DefaultPolicyName = "Default"
|
||||||
|
// DefaultPolicyDescription is a description for the Default policy that is created for every account
|
||||||
|
DefaultPolicyDescription = "This is a default policy that allows connections between all the resources"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
firewallRuleDirectionIN = 0
|
firewallRuleDirectionIN = 0
|
||||||
firewallRuleDirectionOUT = 1
|
firewallRuleDirectionOUT = 1
|
||||||
@ -119,19 +130,6 @@ func (pm *PolicyRule) Copy() *PolicyRule {
|
|||||||
return rule
|
return rule
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToRule converts the PolicyRule to a legacy representation of the Rule (for backwards compatibility)
|
|
||||||
func (pm *PolicyRule) ToRule() *Rule {
|
|
||||||
return &Rule{
|
|
||||||
ID: pm.ID,
|
|
||||||
Name: pm.Name,
|
|
||||||
Description: pm.Description,
|
|
||||||
Disabled: !pm.Enabled,
|
|
||||||
Flow: TrafficFlowBidirect,
|
|
||||||
Destination: pm.Destinations,
|
|
||||||
Source: pm.Sources,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Policy of the Rego query
|
// Policy of the Rego query
|
||||||
type Policy struct {
|
type Policy struct {
|
||||||
// ID of the policy'
|
// ID of the policy'
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
package server
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// TrafficFlowType defines allowed direction of the traffic in the rule
|
|
||||||
type TrafficFlowType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// TrafficFlowBidirect allows traffic to both direction
|
|
||||||
TrafficFlowBidirect TrafficFlowType = iota
|
|
||||||
// TrafficFlowBidirectString allows traffic to both direction
|
|
||||||
TrafficFlowBidirectString = "bidirect"
|
|
||||||
// DefaultRuleName is a name for the Default rule that is created for every account
|
|
||||||
DefaultRuleName = "Default"
|
|
||||||
// DefaultRuleDescription is a description for the Default rule that is created for every account
|
|
||||||
DefaultRuleDescription = "This is a default rule that allows connections between all the resources"
|
|
||||||
// DefaultPolicyName is a name for the Default policy that is created for every account
|
|
||||||
DefaultPolicyName = "Default"
|
|
||||||
// DefaultPolicyDescription is a description for the Default policy that is created for every account
|
|
||||||
DefaultPolicyDescription = "This is a default policy that allows connections between all the resources"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Rule of ACL for groups
|
|
||||||
type Rule struct {
|
|
||||||
// ID of the rule
|
|
||||||
ID string
|
|
||||||
|
|
||||||
// AccountID is a reference to Account that this object belongs
|
|
||||||
AccountID string `json:"-" gorm:"index"`
|
|
||||||
|
|
||||||
// Name of the rule visible in the UI
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// Description of the rule visible in the UI
|
|
||||||
Description string
|
|
||||||
|
|
||||||
// Disabled status of rule in the system
|
|
||||||
Disabled bool
|
|
||||||
|
|
||||||
// Source list of groups IDs of peers
|
|
||||||
Source []string `gorm:"serializer:json"`
|
|
||||||
|
|
||||||
// Destination list of groups IDs of peers
|
|
||||||
Destination []string `gorm:"serializer:json"`
|
|
||||||
|
|
||||||
// Flow of the traffic allowed by the rule
|
|
||||||
Flow TrafficFlowType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Rule) Copy() *Rule {
|
|
||||||
rule := &Rule{
|
|
||||||
ID: r.ID,
|
|
||||||
Name: r.Name,
|
|
||||||
Description: r.Description,
|
|
||||||
Disabled: r.Disabled,
|
|
||||||
Source: make([]string, len(r.Source)),
|
|
||||||
Destination: make([]string, len(r.Destination)),
|
|
||||||
Flow: r.Flow,
|
|
||||||
}
|
|
||||||
copy(rule.Source, r.Source)
|
|
||||||
copy(rule.Destination, r.Destination)
|
|
||||||
return rule
|
|
||||||
}
|
|
||||||
|
|
||||||
// EventMeta returns activity event meta related to this rule
|
|
||||||
func (r *Rule) EventMeta() map[string]any {
|
|
||||||
return map[string]any{"name": r.Name}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToPolicyRule converts a Rule to a PolicyRule object
|
|
||||||
func (r *Rule) ToPolicyRule() *PolicyRule {
|
|
||||||
if r == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &PolicyRule{
|
|
||||||
ID: r.ID,
|
|
||||||
Name: r.Name,
|
|
||||||
Enabled: !r.Disabled,
|
|
||||||
Description: r.Description,
|
|
||||||
Destinations: r.Destination,
|
|
||||||
Sources: r.Source,
|
|
||||||
Bidirectional: true,
|
|
||||||
Protocol: PolicyRuleProtocolALL,
|
|
||||||
Action: PolicyTrafficActionAccept,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RuleToPolicy converts a Rule to a Policy query object
|
|
||||||
func RuleToPolicy(rule *Rule) (*Policy, error) {
|
|
||||||
if rule == nil {
|
|
||||||
return nil, fmt.Errorf("rule is empty")
|
|
||||||
}
|
|
||||||
return &Policy{
|
|
||||||
ID: rule.ID,
|
|
||||||
Name: rule.Name,
|
|
||||||
Description: rule.Description,
|
|
||||||
Enabled: !rule.Disabled,
|
|
||||||
Rules: []*PolicyRule{rule.ToPolicyRule()},
|
|
||||||
}, nil
|
|
||||||
}
|
|
@ -64,7 +64,7 @@ func NewSqliteStore(dataDir string, metrics telemetry.AppMetrics) (*SqliteStore,
|
|||||||
sql.SetMaxOpenConns(conns) // TODO: make it configurable
|
sql.SetMaxOpenConns(conns) // TODO: make it configurable
|
||||||
|
|
||||||
err = db.AutoMigrate(
|
err = db.AutoMigrate(
|
||||||
&SetupKey{}, &nbpeer.Peer{}, &User{}, &PersonalAccessToken{}, &Group{}, &Rule{},
|
&SetupKey{}, &nbpeer.Peer{}, &User{}, &PersonalAccessToken{}, &Group{},
|
||||||
&Account{}, &Policy{}, &PolicyRule{}, &route.Route{}, &nbdns.NameServerGroup{},
|
&Account{}, &Policy{}, &PolicyRule{}, &route.Route{}, &nbdns.NameServerGroup{},
|
||||||
&installation{}, &account.ExtraSettings{}, &posture.Checks{}, &nbpeer.NetworkAddress{},
|
&installation{}, &account.ExtraSettings{}, &posture.Checks{}, &nbpeer.NetworkAddress{},
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user