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
@@ -119,6 +119,153 @@ func (DeviceAuthorizationFlowProvider) EnumDescriptor() ([]byte, []int) {
|
||||
return file_management_proto_rawDescGZIP(), []int{17, 0}
|
||||
}
|
||||
|
||||
type FirewallRuleDirection int32
|
||||
|
||||
const (
|
||||
FirewallRule_IN FirewallRuleDirection = 0
|
||||
FirewallRule_OUT FirewallRuleDirection = 1
|
||||
)
|
||||
|
||||
// Enum value maps for FirewallRuleDirection.
|
||||
var (
|
||||
FirewallRuleDirection_name = map[int32]string{
|
||||
0: "IN",
|
||||
1: "OUT",
|
||||
}
|
||||
FirewallRuleDirection_value = map[string]int32{
|
||||
"IN": 0,
|
||||
"OUT": 1,
|
||||
}
|
||||
)
|
||||
|
||||
func (x FirewallRuleDirection) Enum() *FirewallRuleDirection {
|
||||
p := new(FirewallRuleDirection)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x FirewallRuleDirection) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (FirewallRuleDirection) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_management_proto_enumTypes[2].Descriptor()
|
||||
}
|
||||
|
||||
func (FirewallRuleDirection) Type() protoreflect.EnumType {
|
||||
return &file_management_proto_enumTypes[2]
|
||||
}
|
||||
|
||||
func (x FirewallRuleDirection) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FirewallRuleDirection.Descriptor instead.
|
||||
func (FirewallRuleDirection) EnumDescriptor() ([]byte, []int) {
|
||||
return file_management_proto_rawDescGZIP(), []int{25, 0}
|
||||
}
|
||||
|
||||
type FirewallRuleAction int32
|
||||
|
||||
const (
|
||||
FirewallRule_ACCEPT FirewallRuleAction = 0
|
||||
FirewallRule_DROP FirewallRuleAction = 1
|
||||
)
|
||||
|
||||
// Enum value maps for FirewallRuleAction.
|
||||
var (
|
||||
FirewallRuleAction_name = map[int32]string{
|
||||
0: "ACCEPT",
|
||||
1: "DROP",
|
||||
}
|
||||
FirewallRuleAction_value = map[string]int32{
|
||||
"ACCEPT": 0,
|
||||
"DROP": 1,
|
||||
}
|
||||
)
|
||||
|
||||
func (x FirewallRuleAction) Enum() *FirewallRuleAction {
|
||||
p := new(FirewallRuleAction)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x FirewallRuleAction) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (FirewallRuleAction) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_management_proto_enumTypes[3].Descriptor()
|
||||
}
|
||||
|
||||
func (FirewallRuleAction) Type() protoreflect.EnumType {
|
||||
return &file_management_proto_enumTypes[3]
|
||||
}
|
||||
|
||||
func (x FirewallRuleAction) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FirewallRuleAction.Descriptor instead.
|
||||
func (FirewallRuleAction) EnumDescriptor() ([]byte, []int) {
|
||||
return file_management_proto_rawDescGZIP(), []int{25, 1}
|
||||
}
|
||||
|
||||
type FirewallRuleProtocol int32
|
||||
|
||||
const (
|
||||
FirewallRule_UNKNOWN FirewallRuleProtocol = 0
|
||||
FirewallRule_ALL FirewallRuleProtocol = 1
|
||||
FirewallRule_TCP FirewallRuleProtocol = 2
|
||||
FirewallRule_UDP FirewallRuleProtocol = 3
|
||||
FirewallRule_ICMP FirewallRuleProtocol = 4
|
||||
)
|
||||
|
||||
// Enum value maps for FirewallRuleProtocol.
|
||||
var (
|
||||
FirewallRuleProtocol_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "ALL",
|
||||
2: "TCP",
|
||||
3: "UDP",
|
||||
4: "ICMP",
|
||||
}
|
||||
FirewallRuleProtocol_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"ALL": 1,
|
||||
"TCP": 2,
|
||||
"UDP": 3,
|
||||
"ICMP": 4,
|
||||
}
|
||||
)
|
||||
|
||||
func (x FirewallRuleProtocol) Enum() *FirewallRuleProtocol {
|
||||
p := new(FirewallRuleProtocol)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x FirewallRuleProtocol) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (FirewallRuleProtocol) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_management_proto_enumTypes[4].Descriptor()
|
||||
}
|
||||
|
||||
func (FirewallRuleProtocol) Type() protoreflect.EnumType {
|
||||
return &file_management_proto_enumTypes[4]
|
||||
}
|
||||
|
||||
func (x FirewallRuleProtocol) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FirewallRuleProtocol.Descriptor instead.
|
||||
func (FirewallRuleProtocol) EnumDescriptor() ([]byte, []int) {
|
||||
return file_management_proto_rawDescGZIP(), []int{25, 2}
|
||||
}
|
||||
|
||||
type EncryptedMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -995,6 +1142,8 @@ type NetworkMap struct {
|
||||
DNSConfig *DNSConfig `protobuf:"bytes,6,opt,name=DNSConfig,proto3" json:"DNSConfig,omitempty"`
|
||||
// RemotePeerConfig represents a list of remote peers that the receiver can connect to
|
||||
OfflinePeers []*RemotePeerConfig `protobuf:"bytes,7,rep,name=offlinePeers,proto3" json:"offlinePeers,omitempty"`
|
||||
// FirewallRule represents a list of firewall rules to be applied to peer
|
||||
FirewallRules []*FirewallRule `protobuf:"bytes,8,rep,name=FirewallRules,proto3" json:"FirewallRules,omitempty"`
|
||||
}
|
||||
|
||||
func (x *NetworkMap) Reset() {
|
||||
@@ -1078,6 +1227,13 @@ func (x *NetworkMap) GetOfflinePeers() []*RemotePeerConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NetworkMap) GetFirewallRules() []*FirewallRule {
|
||||
if x != nil {
|
||||
return x.FirewallRules
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemotePeerConfig represents a configuration of a remote peer.
|
||||
// The properties are used to configure WireGuard Peers sections
|
||||
type RemotePeerConfig struct {
|
||||
@@ -1849,6 +2005,86 @@ func (x *NameServer) GetPort() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// FirewallRule represents a firewall rule
|
||||
type FirewallRule struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PeerIP string `protobuf:"bytes,1,opt,name=PeerIP,proto3" json:"PeerIP,omitempty"`
|
||||
Direction FirewallRuleDirection `protobuf:"varint,2,opt,name=Direction,proto3,enum=management.FirewallRuleDirection" json:"Direction,omitempty"`
|
||||
Action FirewallRuleAction `protobuf:"varint,3,opt,name=Action,proto3,enum=management.FirewallRuleAction" json:"Action,omitempty"`
|
||||
Protocol FirewallRuleProtocol `protobuf:"varint,4,opt,name=Protocol,proto3,enum=management.FirewallRuleProtocol" json:"Protocol,omitempty"`
|
||||
Port string `protobuf:"bytes,5,opt,name=Port,proto3" json:"Port,omitempty"`
|
||||
}
|
||||
|
||||
func (x *FirewallRule) Reset() {
|
||||
*x = FirewallRule{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_management_proto_msgTypes[25]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FirewallRule) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FirewallRule) ProtoMessage() {}
|
||||
|
||||
func (x *FirewallRule) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_management_proto_msgTypes[25]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FirewallRule.ProtoReflect.Descriptor instead.
|
||||
func (*FirewallRule) Descriptor() ([]byte, []int) {
|
||||
return file_management_proto_rawDescGZIP(), []int{25}
|
||||
}
|
||||
|
||||
func (x *FirewallRule) GetPeerIP() string {
|
||||
if x != nil {
|
||||
return x.PeerIP
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *FirewallRule) GetDirection() FirewallRuleDirection {
|
||||
if x != nil {
|
||||
return x.Direction
|
||||
}
|
||||
return FirewallRule_IN
|
||||
}
|
||||
|
||||
func (x *FirewallRule) GetAction() FirewallRuleAction {
|
||||
if x != nil {
|
||||
return x.Action
|
||||
}
|
||||
return FirewallRule_ACCEPT
|
||||
}
|
||||
|
||||
func (x *FirewallRule) GetProtocol() FirewallRuleProtocol {
|
||||
if x != nil {
|
||||
return x.Protocol
|
||||
}
|
||||
return FirewallRule_UNKNOWN
|
||||
}
|
||||
|
||||
func (x *FirewallRule) GetPort() string {
|
||||
if x != nil {
|
||||
return x.Port
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_management_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_management_proto_rawDesc = []byte{
|
||||
@@ -1966,7 +2202,7 @@ var file_management_proto_rawDesc = []byte{
|
||||
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x73, 0x73, 0x68, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x22, 0xee, 0x02, 0x0a, 0x0a, 0x4e, 0x65, 0x74,
|
||||
0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x22, 0xae, 0x03, 0x0a, 0x0a, 0x4e, 0x65, 0x74,
|
||||
0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x69, 0x61,
|
||||
0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12,
|
||||
0x36, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20,
|
||||
@@ -1989,7 +2225,11 @@ var file_management_proto_rawDesc = []byte{
|
||||
0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
|
||||
0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74,
|
||||
0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x6f, 0x66, 0x66,
|
||||
0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x10, 0x52, 0x65,
|
||||
0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x3e, 0x0a, 0x0d, 0x46, 0x69, 0x72,
|
||||
0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x18, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x69,
|
||||
0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x46, 0x69, 0x72, 0x65,
|
||||
0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x10, 0x52, 0x65,
|
||||
0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a,
|
||||
0x0a, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x6c,
|
||||
@@ -2083,32 +2323,55 @@ var file_management_proto_rawDesc = []byte{
|
||||
0x76, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x02, 0x49, 0x50, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x03, 0x52, 0x06, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50,
|
||||
0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x32,
|
||||
0xf7, 0x02, 0x0a, 0x11, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1c,
|
||||
0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22,
|
||||
0xf0, 0x02, 0x0a, 0x0c, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x50, 0x12, 0x40, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x6d, 0x61,
|
||||
0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c,
|
||||
0x6c, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
|
||||
0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x06, 0x41, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x61, 0x6e,
|
||||
0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c,
|
||||
0x52, 0x75, 0x6c, 0x65, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
||||
0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x06, 0x0a, 0x02, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4f,
|
||||
0x55, 0x54, 0x10, 0x01, 0x22, 0x1e, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a,
|
||||
0x0a, 0x06, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x52,
|
||||
0x4f, 0x50, 0x10, 0x01, 0x22, 0x3c, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a,
|
||||
0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x12,
|
||||
0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x43, 0x4d, 0x50,
|
||||
0x10, 0x04, 0x32, 0xf7, 0x02, 0x0a, 0x11, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69,
|
||||
0x6e, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45,
|
||||
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a,
|
||||
0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63,
|
||||
0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12,
|
||||
0x46, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x6d, 0x61, 0x6e,
|
||||
0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65,
|
||||
0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x09, 0x69,
|
||||
0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x6d, 0x61,
|
||||
0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00,
|
||||
0x12, 0x5a, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74,
|
||||
0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x1c,
|
||||
0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72,
|
||||
0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70,
|
||||
0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x04,
|
||||
0x53, 0x79, 0x6e, 0x63, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||
0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x4b, 0x65, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x09, 0x69, 0x73, 0x48, 0x65,
|
||||
0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x5a, 0x0a,
|
||||
0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
|
||||
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x1c, 0x2e, 0x6d, 0x61,
|
||||
0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74,
|
||||
0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
|
||||
0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64,
|
||||
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -2123,81 +2386,89 @@ func file_management_proto_rawDescGZIP() []byte {
|
||||
return file_management_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_management_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_management_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
|
||||
var file_management_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
|
||||
var file_management_proto_msgTypes = make([]protoimpl.MessageInfo, 26)
|
||||
var file_management_proto_goTypes = []interface{}{
|
||||
(HostConfig_Protocol)(0), // 0: management.HostConfig.Protocol
|
||||
(DeviceAuthorizationFlowProvider)(0), // 1: management.DeviceAuthorizationFlow.provider
|
||||
(*EncryptedMessage)(nil), // 2: management.EncryptedMessage
|
||||
(*SyncRequest)(nil), // 3: management.SyncRequest
|
||||
(*SyncResponse)(nil), // 4: management.SyncResponse
|
||||
(*LoginRequest)(nil), // 5: management.LoginRequest
|
||||
(*PeerKeys)(nil), // 6: management.PeerKeys
|
||||
(*PeerSystemMeta)(nil), // 7: management.PeerSystemMeta
|
||||
(*LoginResponse)(nil), // 8: management.LoginResponse
|
||||
(*ServerKeyResponse)(nil), // 9: management.ServerKeyResponse
|
||||
(*Empty)(nil), // 10: management.Empty
|
||||
(*WiretrusteeConfig)(nil), // 11: management.WiretrusteeConfig
|
||||
(*HostConfig)(nil), // 12: management.HostConfig
|
||||
(*ProtectedHostConfig)(nil), // 13: management.ProtectedHostConfig
|
||||
(*PeerConfig)(nil), // 14: management.PeerConfig
|
||||
(*NetworkMap)(nil), // 15: management.NetworkMap
|
||||
(*RemotePeerConfig)(nil), // 16: management.RemotePeerConfig
|
||||
(*SSHConfig)(nil), // 17: management.SSHConfig
|
||||
(*DeviceAuthorizationFlowRequest)(nil), // 18: management.DeviceAuthorizationFlowRequest
|
||||
(*DeviceAuthorizationFlow)(nil), // 19: management.DeviceAuthorizationFlow
|
||||
(*ProviderConfig)(nil), // 20: management.ProviderConfig
|
||||
(*Route)(nil), // 21: management.Route
|
||||
(*DNSConfig)(nil), // 22: management.DNSConfig
|
||||
(*CustomZone)(nil), // 23: management.CustomZone
|
||||
(*SimpleRecord)(nil), // 24: management.SimpleRecord
|
||||
(*NameServerGroup)(nil), // 25: management.NameServerGroup
|
||||
(*NameServer)(nil), // 26: management.NameServer
|
||||
(*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp
|
||||
(FirewallRuleDirection)(0), // 2: management.FirewallRule.direction
|
||||
(FirewallRuleAction)(0), // 3: management.FirewallRule.action
|
||||
(FirewallRuleProtocol)(0), // 4: management.FirewallRule.protocol
|
||||
(*EncryptedMessage)(nil), // 5: management.EncryptedMessage
|
||||
(*SyncRequest)(nil), // 6: management.SyncRequest
|
||||
(*SyncResponse)(nil), // 7: management.SyncResponse
|
||||
(*LoginRequest)(nil), // 8: management.LoginRequest
|
||||
(*PeerKeys)(nil), // 9: management.PeerKeys
|
||||
(*PeerSystemMeta)(nil), // 10: management.PeerSystemMeta
|
||||
(*LoginResponse)(nil), // 11: management.LoginResponse
|
||||
(*ServerKeyResponse)(nil), // 12: management.ServerKeyResponse
|
||||
(*Empty)(nil), // 13: management.Empty
|
||||
(*WiretrusteeConfig)(nil), // 14: management.WiretrusteeConfig
|
||||
(*HostConfig)(nil), // 15: management.HostConfig
|
||||
(*ProtectedHostConfig)(nil), // 16: management.ProtectedHostConfig
|
||||
(*PeerConfig)(nil), // 17: management.PeerConfig
|
||||
(*NetworkMap)(nil), // 18: management.NetworkMap
|
||||
(*RemotePeerConfig)(nil), // 19: management.RemotePeerConfig
|
||||
(*SSHConfig)(nil), // 20: management.SSHConfig
|
||||
(*DeviceAuthorizationFlowRequest)(nil), // 21: management.DeviceAuthorizationFlowRequest
|
||||
(*DeviceAuthorizationFlow)(nil), // 22: management.DeviceAuthorizationFlow
|
||||
(*ProviderConfig)(nil), // 23: management.ProviderConfig
|
||||
(*Route)(nil), // 24: management.Route
|
||||
(*DNSConfig)(nil), // 25: management.DNSConfig
|
||||
(*CustomZone)(nil), // 26: management.CustomZone
|
||||
(*SimpleRecord)(nil), // 27: management.SimpleRecord
|
||||
(*NameServerGroup)(nil), // 28: management.NameServerGroup
|
||||
(*NameServer)(nil), // 29: management.NameServer
|
||||
(*FirewallRule)(nil), // 30: management.FirewallRule
|
||||
(*timestamppb.Timestamp)(nil), // 31: google.protobuf.Timestamp
|
||||
}
|
||||
var file_management_proto_depIdxs = []int32{
|
||||
11, // 0: management.SyncResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig
|
||||
14, // 1: management.SyncResponse.peerConfig:type_name -> management.PeerConfig
|
||||
16, // 2: management.SyncResponse.remotePeers:type_name -> management.RemotePeerConfig
|
||||
15, // 3: management.SyncResponse.NetworkMap:type_name -> management.NetworkMap
|
||||
7, // 4: management.LoginRequest.meta:type_name -> management.PeerSystemMeta
|
||||
6, // 5: management.LoginRequest.peerKeys:type_name -> management.PeerKeys
|
||||
11, // 6: management.LoginResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig
|
||||
14, // 7: management.LoginResponse.peerConfig:type_name -> management.PeerConfig
|
||||
27, // 8: management.ServerKeyResponse.expiresAt:type_name -> google.protobuf.Timestamp
|
||||
12, // 9: management.WiretrusteeConfig.stuns:type_name -> management.HostConfig
|
||||
13, // 10: management.WiretrusteeConfig.turns:type_name -> management.ProtectedHostConfig
|
||||
12, // 11: management.WiretrusteeConfig.signal:type_name -> management.HostConfig
|
||||
14, // 0: management.SyncResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig
|
||||
17, // 1: management.SyncResponse.peerConfig:type_name -> management.PeerConfig
|
||||
19, // 2: management.SyncResponse.remotePeers:type_name -> management.RemotePeerConfig
|
||||
18, // 3: management.SyncResponse.NetworkMap:type_name -> management.NetworkMap
|
||||
10, // 4: management.LoginRequest.meta:type_name -> management.PeerSystemMeta
|
||||
9, // 5: management.LoginRequest.peerKeys:type_name -> management.PeerKeys
|
||||
14, // 6: management.LoginResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig
|
||||
17, // 7: management.LoginResponse.peerConfig:type_name -> management.PeerConfig
|
||||
31, // 8: management.ServerKeyResponse.expiresAt:type_name -> google.protobuf.Timestamp
|
||||
15, // 9: management.WiretrusteeConfig.stuns:type_name -> management.HostConfig
|
||||
16, // 10: management.WiretrusteeConfig.turns:type_name -> management.ProtectedHostConfig
|
||||
15, // 11: management.WiretrusteeConfig.signal:type_name -> management.HostConfig
|
||||
0, // 12: management.HostConfig.protocol:type_name -> management.HostConfig.Protocol
|
||||
12, // 13: management.ProtectedHostConfig.hostConfig:type_name -> management.HostConfig
|
||||
17, // 14: management.PeerConfig.sshConfig:type_name -> management.SSHConfig
|
||||
14, // 15: management.NetworkMap.peerConfig:type_name -> management.PeerConfig
|
||||
16, // 16: management.NetworkMap.remotePeers:type_name -> management.RemotePeerConfig
|
||||
21, // 17: management.NetworkMap.Routes:type_name -> management.Route
|
||||
22, // 18: management.NetworkMap.DNSConfig:type_name -> management.DNSConfig
|
||||
16, // 19: management.NetworkMap.offlinePeers:type_name -> management.RemotePeerConfig
|
||||
17, // 20: management.RemotePeerConfig.sshConfig:type_name -> management.SSHConfig
|
||||
1, // 21: management.DeviceAuthorizationFlow.Provider:type_name -> management.DeviceAuthorizationFlow.provider
|
||||
20, // 22: management.DeviceAuthorizationFlow.ProviderConfig:type_name -> management.ProviderConfig
|
||||
25, // 23: management.DNSConfig.NameServerGroups:type_name -> management.NameServerGroup
|
||||
23, // 24: management.DNSConfig.CustomZones:type_name -> management.CustomZone
|
||||
24, // 25: management.CustomZone.Records:type_name -> management.SimpleRecord
|
||||
26, // 26: management.NameServerGroup.NameServers:type_name -> management.NameServer
|
||||
2, // 27: management.ManagementService.Login:input_type -> management.EncryptedMessage
|
||||
2, // 28: management.ManagementService.Sync:input_type -> management.EncryptedMessage
|
||||
10, // 29: management.ManagementService.GetServerKey:input_type -> management.Empty
|
||||
10, // 30: management.ManagementService.isHealthy:input_type -> management.Empty
|
||||
2, // 31: management.ManagementService.GetDeviceAuthorizationFlow:input_type -> management.EncryptedMessage
|
||||
2, // 32: management.ManagementService.Login:output_type -> management.EncryptedMessage
|
||||
2, // 33: management.ManagementService.Sync:output_type -> management.EncryptedMessage
|
||||
9, // 34: management.ManagementService.GetServerKey:output_type -> management.ServerKeyResponse
|
||||
10, // 35: management.ManagementService.isHealthy:output_type -> management.Empty
|
||||
2, // 36: management.ManagementService.GetDeviceAuthorizationFlow:output_type -> management.EncryptedMessage
|
||||
32, // [32:37] is the sub-list for method output_type
|
||||
27, // [27:32] is the sub-list for method input_type
|
||||
27, // [27:27] is the sub-list for extension type_name
|
||||
27, // [27:27] is the sub-list for extension extendee
|
||||
0, // [0:27] is the sub-list for field type_name
|
||||
15, // 13: management.ProtectedHostConfig.hostConfig:type_name -> management.HostConfig
|
||||
20, // 14: management.PeerConfig.sshConfig:type_name -> management.SSHConfig
|
||||
17, // 15: management.NetworkMap.peerConfig:type_name -> management.PeerConfig
|
||||
19, // 16: management.NetworkMap.remotePeers:type_name -> management.RemotePeerConfig
|
||||
24, // 17: management.NetworkMap.Routes:type_name -> management.Route
|
||||
25, // 18: management.NetworkMap.DNSConfig:type_name -> management.DNSConfig
|
||||
19, // 19: management.NetworkMap.offlinePeers:type_name -> management.RemotePeerConfig
|
||||
30, // 20: management.NetworkMap.FirewallRules:type_name -> management.FirewallRule
|
||||
20, // 21: management.RemotePeerConfig.sshConfig:type_name -> management.SSHConfig
|
||||
1, // 22: management.DeviceAuthorizationFlow.Provider:type_name -> management.DeviceAuthorizationFlow.provider
|
||||
23, // 23: management.DeviceAuthorizationFlow.ProviderConfig:type_name -> management.ProviderConfig
|
||||
28, // 24: management.DNSConfig.NameServerGroups:type_name -> management.NameServerGroup
|
||||
26, // 25: management.DNSConfig.CustomZones:type_name -> management.CustomZone
|
||||
27, // 26: management.CustomZone.Records:type_name -> management.SimpleRecord
|
||||
29, // 27: management.NameServerGroup.NameServers:type_name -> management.NameServer
|
||||
2, // 28: management.FirewallRule.Direction:type_name -> management.FirewallRule.direction
|
||||
3, // 29: management.FirewallRule.Action:type_name -> management.FirewallRule.action
|
||||
4, // 30: management.FirewallRule.Protocol:type_name -> management.FirewallRule.protocol
|
||||
5, // 31: management.ManagementService.Login:input_type -> management.EncryptedMessage
|
||||
5, // 32: management.ManagementService.Sync:input_type -> management.EncryptedMessage
|
||||
13, // 33: management.ManagementService.GetServerKey:input_type -> management.Empty
|
||||
13, // 34: management.ManagementService.isHealthy:input_type -> management.Empty
|
||||
5, // 35: management.ManagementService.GetDeviceAuthorizationFlow:input_type -> management.EncryptedMessage
|
||||
5, // 36: management.ManagementService.Login:output_type -> management.EncryptedMessage
|
||||
5, // 37: management.ManagementService.Sync:output_type -> management.EncryptedMessage
|
||||
12, // 38: management.ManagementService.GetServerKey:output_type -> management.ServerKeyResponse
|
||||
13, // 39: management.ManagementService.isHealthy:output_type -> management.Empty
|
||||
5, // 40: management.ManagementService.GetDeviceAuthorizationFlow:output_type -> management.EncryptedMessage
|
||||
36, // [36:41] is the sub-list for method output_type
|
||||
31, // [31:36] is the sub-list for method input_type
|
||||
31, // [31:31] is the sub-list for extension type_name
|
||||
31, // [31:31] is the sub-list for extension extendee
|
||||
0, // [0:31] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_management_proto_init() }
|
||||
@@ -2506,14 +2777,26 @@ func file_management_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_management_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*FirewallRule); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_management_proto_rawDesc,
|
||||
NumEnums: 2,
|
||||
NumMessages: 25,
|
||||
NumEnums: 5,
|
||||
NumMessages: 26,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@@ -186,6 +186,9 @@ message NetworkMap {
|
||||
|
||||
// RemotePeerConfig represents a list of remote peers that the receiver can connect to
|
||||
repeated RemotePeerConfig offlinePeers = 7;
|
||||
|
||||
// FirewallRule represents a list of firewall rules to be applied to peer
|
||||
repeated FirewallRule FirewallRules = 8;
|
||||
}
|
||||
|
||||
// RemotePeerConfig represents a configuration of a remote peer.
|
||||
@@ -297,4 +300,29 @@ message NameServer {
|
||||
string IP = 1;
|
||||
int64 NSType = 2;
|
||||
int64 Port = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// FirewallRule represents a firewall rule
|
||||
message FirewallRule {
|
||||
string PeerIP = 1;
|
||||
direction Direction = 2;
|
||||
action Action = 3;
|
||||
protocol Protocol = 4;
|
||||
string Port = 5;
|
||||
|
||||
enum direction {
|
||||
IN = 0;
|
||||
OUT = 1;
|
||||
}
|
||||
enum action {
|
||||
ACCEPT = 0;
|
||||
DROP = 1;
|
||||
}
|
||||
enum protocol {
|
||||
UNKNOWN = 0;
|
||||
ALL = 1;
|
||||
TCP = 2;
|
||||
UDP = 3;
|
||||
ICMP = 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ func (a *Account) GetGroup(groupID string) *Group {
|
||||
|
||||
// GetPeerNetworkMap returns a group by ID if exists, nil otherwise
|
||||
func (a *Account) GetPeerNetworkMap(peerID, dnsDomain string) *NetworkMap {
|
||||
aclPeers := a.getPeersByACL(peerID)
|
||||
aclPeers, firewallRules := a.getPeerConnectionResources(peerID)
|
||||
// exclude expired peers
|
||||
var peersToConnect []*Peer
|
||||
var expiredPeers []*Peer
|
||||
@@ -317,11 +317,12 @@ func (a *Account) GetPeerNetworkMap(peerID, dnsDomain string) *NetworkMap {
|
||||
}
|
||||
|
||||
return &NetworkMap{
|
||||
Peers: peersToConnect,
|
||||
Network: a.Network.Copy(),
|
||||
Routes: routesUpdate,
|
||||
DNSConfig: dnsUpdate,
|
||||
OfflinePeers: expiredPeers,
|
||||
Peers: peersToConnect,
|
||||
Network: a.Network.Copy(),
|
||||
Routes: routesUpdate,
|
||||
DNSConfig: dnsUpdate,
|
||||
OfflinePeers: expiredPeers,
|
||||
FirewallRules: firewallRules,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -919,17 +919,14 @@ func TestAccountManager_NetworkUpdates(t *testing.T) {
|
||||
Enabled: true,
|
||||
Rules: []*PolicyRule{
|
||||
{
|
||||
Enabled: true,
|
||||
Sources: []string{"group-id"},
|
||||
Destinations: []string{"group-id"},
|
||||
Action: PolicyTrafficActionAccept,
|
||||
Enabled: true,
|
||||
Sources: []string{"group-id"},
|
||||
Destinations: []string{"group-id"},
|
||||
Bidirectional: true,
|
||||
Action: PolicyTrafficActionAccept,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := policy.UpdateQueryFromRules(); err != nil {
|
||||
t.Errorf("update policy query from rules: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
t.Run("save group update", func(t *testing.T) {
|
||||
|
||||
@@ -129,12 +129,11 @@ func restore(file string) (*FileStore, error) {
|
||||
store.PrivateDomain2AccountID[account.Domain] = accountID
|
||||
}
|
||||
|
||||
// TODO: policy query generated from the Go template and rule object.
|
||||
// We need to refactor this part to avoid using templating for policies queries building
|
||||
// and drop this migration part.
|
||||
// TODO: delete this block after migration
|
||||
policies := make(map[string]int, len(account.Policies))
|
||||
for i, policy := range account.Policies {
|
||||
policies[policy.ID] = i
|
||||
policy.UpgradeAndFix()
|
||||
}
|
||||
if account.Policies == nil {
|
||||
account.Policies = make([]*Policy, 0)
|
||||
@@ -145,9 +144,9 @@ func restore(file string) (*FileStore, error) {
|
||||
log.Errorf("unable to migrate rule to policy: %v", err)
|
||||
continue
|
||||
}
|
||||
if i, ok := policies[policy.ID]; ok {
|
||||
account.Policies[i] = policy
|
||||
} else {
|
||||
// don't update policies from rules, rules deprecated,
|
||||
// only append not existed rules as part of the migration process
|
||||
if _, ok := policies[policy.ID]; !ok {
|
||||
account.Policies = append(account.Policies, policy)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,10 +285,7 @@ func TestRestorePolicies_Migration(t *testing.T) {
|
||||
require.Equal(t, policy.Description,
|
||||
"This is a default rule that allows connections between all the resources",
|
||||
"failed to restore a FileStore file - missing Account Policies Description")
|
||||
expectedPolicy := policy.Copy()
|
||||
err = expectedPolicy.UpdateQueryFromRules()
|
||||
require.NoError(t, err, "failed to upldate query")
|
||||
require.Equal(t, policy.Query, expectedPolicy.Query, "failed to restore a FileStore file - missing Account Policies Query")
|
||||
require.Len(t, policy.Rules, 1, "failed to restore a FileStore file - missing Account Policy Rules")
|
||||
require.Equal(t, policy.Rules[0].Action, PolicyTrafficActionAccept, "failed to restore a FileStore file - missing Account Policies Action")
|
||||
require.Equal(t, policy.Rules[0].Destinations,
|
||||
|
||||
@@ -436,6 +436,8 @@ func toSyncResponse(config *Config, peer *Peer, turnCredentials *TURNCredentials
|
||||
|
||||
offlinePeers := toRemotePeerConfig(networkMap.OfflinePeers, dnsName)
|
||||
|
||||
firewallRules := toProtocolFirewallRules(networkMap.FirewallRules)
|
||||
|
||||
return &proto.SyncResponse{
|
||||
WiretrusteeConfig: wtConfig,
|
||||
PeerConfig: pConfig,
|
||||
@@ -449,6 +451,7 @@ func toSyncResponse(config *Config, peer *Peer, turnCredentials *TURNCredentials
|
||||
RemotePeersIsEmpty: len(remotePeers) == 0,
|
||||
Routes: routesUpdate,
|
||||
DNSConfig: dnsUpdate,
|
||||
FirewallRules: firewallRules,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -25,11 +25,12 @@ const (
|
||||
)
|
||||
|
||||
type NetworkMap struct {
|
||||
Peers []*Peer
|
||||
Network *Network
|
||||
Routes []*route.Route
|
||||
DNSConfig nbdns.Config
|
||||
OfflinePeers []*Peer
|
||||
Peers []*Peer
|
||||
Network *Network
|
||||
Routes []*route.Route
|
||||
DNSConfig nbdns.Config
|
||||
OfflinePeers []*Peer
|
||||
FirewallRules []*FirewallRule
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
|
||||
@@ -225,8 +225,7 @@ func (am *DefaultAccountManager) GetPeers(accountID, userID string) ([]*Peer, er
|
||||
|
||||
// fetch all the peers that have access to the user's peers
|
||||
for _, peer := range peers {
|
||||
// TODO: use firewall rules
|
||||
aclPeers := account.getPeersByACL(peer.ID)
|
||||
aclPeers, _ := account.getPeerConnectionResources(peer.ID)
|
||||
for _, p := range aclPeers {
|
||||
peersMap[p.ID] = p
|
||||
}
|
||||
@@ -865,7 +864,7 @@ func (am *DefaultAccountManager) GetPeer(accountID, peerID, userID string) (*Pee
|
||||
}
|
||||
|
||||
for _, p := range userPeers {
|
||||
aclPeers := account.getPeersByACL(p.ID)
|
||||
aclPeers, _ := account.getPeerConnectionResources(p.ID)
|
||||
for _, aclPeer := range aclPeers {
|
||||
if aclPeer.ID == peerID {
|
||||
return peer, nil
|
||||
@@ -884,98 +883,6 @@ func updatePeerMeta(peer *Peer, meta PeerSystemMeta, account *Account) (*Peer, b
|
||||
return peer, false
|
||||
}
|
||||
|
||||
// GetPeerRules returns a list of source or destination rules of a given peer.
|
||||
func (a *Account) GetPeerRules(peerID string) (srcRules []*Rule, dstRules []*Rule) {
|
||||
// Rules are group based so there is no direct access to peers.
|
||||
// First, find all groups that the given peer belongs to
|
||||
peerGroups := make(map[string]struct{})
|
||||
|
||||
for s, group := range a.Groups {
|
||||
for _, peer := range group.Peers {
|
||||
if peerID == peer {
|
||||
peerGroups[s] = struct{}{}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second, find all rules that have discovered source and destination groups
|
||||
srcRulesMap := make(map[string]*Rule)
|
||||
dstRulesMap := make(map[string]*Rule)
|
||||
for _, rule := range a.Rules {
|
||||
for _, g := range rule.Source {
|
||||
if _, ok := peerGroups[g]; ok && srcRulesMap[rule.ID] == nil {
|
||||
srcRules = append(srcRules, rule)
|
||||
srcRulesMap[rule.ID] = rule
|
||||
}
|
||||
}
|
||||
for _, g := range rule.Destination {
|
||||
if _, ok := peerGroups[g]; ok && dstRulesMap[rule.ID] == nil {
|
||||
dstRules = append(dstRules, rule)
|
||||
dstRulesMap[rule.ID] = rule
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return srcRules, dstRules
|
||||
}
|
||||
|
||||
// getPeersByACL returns all peers that given peer has access to.
|
||||
func (a *Account) getPeersByACL(peerID string) []*Peer {
|
||||
var peers []*Peer
|
||||
srcRules, dstRules := a.GetPeerRules(peerID)
|
||||
|
||||
groups := map[string]*Group{}
|
||||
for _, r := range srcRules {
|
||||
if r.Disabled {
|
||||
continue
|
||||
}
|
||||
if r.Flow == TrafficFlowBidirect {
|
||||
for _, gid := range r.Destination {
|
||||
if group, ok := a.Groups[gid]; ok {
|
||||
groups[gid] = group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, r := range dstRules {
|
||||
if r.Disabled {
|
||||
continue
|
||||
}
|
||||
if r.Flow == TrafficFlowBidirect {
|
||||
for _, gid := range r.Source {
|
||||
if group, ok := a.Groups[gid]; ok {
|
||||
groups[gid] = group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
peersSet := make(map[string]struct{})
|
||||
for _, g := range groups {
|
||||
for _, pid := range g.Peers {
|
||||
peer, ok := a.Peers[pid]
|
||||
if !ok {
|
||||
log.Warnf(
|
||||
"peer %s found in group %s but doesn't belong to account %s",
|
||||
pid,
|
||||
g.ID,
|
||||
a.Id,
|
||||
)
|
||||
continue
|
||||
}
|
||||
// exclude original peer
|
||||
if _, ok := peersSet[peer.ID]; peer.ID != peerID && !ok {
|
||||
peersSet[peer.ID] = struct{}{}
|
||||
peers = append(peers, peer.Copy())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return peers
|
||||
}
|
||||
|
||||
// updateAccountPeers updates all peers that belong to an account.
|
||||
// Should be called when changes have to be synced to peers.
|
||||
func (am *DefaultAccountManager) updateAccountPeers(account *Account) error {
|
||||
|
||||
@@ -227,16 +227,13 @@ func TestAccountManager_GetNetworkMapWithPolicy(t *testing.T) {
|
||||
policy.Enabled = true
|
||||
policy.Rules = []*PolicyRule{
|
||||
{
|
||||
Enabled: true,
|
||||
Sources: []string{group1.ID},
|
||||
Destinations: []string{group2.ID},
|
||||
Action: PolicyTrafficActionAccept,
|
||||
Enabled: true,
|
||||
Sources: []string{group1.ID},
|
||||
Destinations: []string{group2.ID},
|
||||
Bidirectional: true,
|
||||
Action: PolicyTrafficActionAccept,
|
||||
},
|
||||
}
|
||||
if err := policy.UpdateQueryFromRules(); err != nil {
|
||||
t.Errorf("expecting policy to be updated, got failure %v", err)
|
||||
return
|
||||
}
|
||||
err = manager.SavePolicy(account.Id, userID, &policy)
|
||||
if err != nil {
|
||||
t.Errorf("expecting rule to be added, got failure %v", err)
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"strings"
|
||||
|
||||
"github.com/netbirdio/netbird/management/proto"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
|
||||
"github.com/open-policy-agent/opa/rego"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// PolicyUpdateOperationType operation type
|
||||
@@ -21,6 +16,12 @@ type PolicyUpdateOperationType int
|
||||
// PolicyTrafficActionType action type for the firewall
|
||||
type PolicyTrafficActionType string
|
||||
|
||||
// PolicyRuleProtocolType type of traffic
|
||||
type PolicyRuleProtocolType string
|
||||
|
||||
// PolicyRuleDirection direction of traffic
|
||||
type PolicyRuleDirection string
|
||||
|
||||
const (
|
||||
// PolicyTrafficActionAccept indicates that the traffic is accepted
|
||||
PolicyTrafficActionAccept = PolicyTrafficActionType("accept")
|
||||
@@ -28,21 +29,35 @@ const (
|
||||
PolicyTrafficActionDrop = PolicyTrafficActionType("drop")
|
||||
)
|
||||
|
||||
const (
|
||||
// PolicyRuleProtocolALL type of traffic
|
||||
PolicyRuleProtocolALL = PolicyRuleProtocolType("all")
|
||||
// PolicyRuleProtocolTCP type of traffic
|
||||
PolicyRuleProtocolTCP = PolicyRuleProtocolType("tcp")
|
||||
// PolicyRuleProtocolUDP type of traffic
|
||||
PolicyRuleProtocolUDP = PolicyRuleProtocolType("udp")
|
||||
// PolicyRuleProtocolICMP type of traffic
|
||||
PolicyRuleProtocolICMP = PolicyRuleProtocolType("icmp")
|
||||
)
|
||||
|
||||
const (
|
||||
// PolicyRuleFlowDirect allows trafic from source to destination
|
||||
PolicyRuleFlowDirect = PolicyRuleDirection("direct")
|
||||
// PolicyRuleFlowBidirect allows traffic to both directions
|
||||
PolicyRuleFlowBidirect = PolicyRuleDirection("bidirect")
|
||||
)
|
||||
|
||||
const (
|
||||
firewallRuleDirectionIN = 0
|
||||
firewallRuleDirectionOUT = 1
|
||||
)
|
||||
|
||||
// PolicyUpdateOperation operation object with type and values to be applied
|
||||
type PolicyUpdateOperation struct {
|
||||
Type PolicyUpdateOperationType
|
||||
Values []string
|
||||
}
|
||||
|
||||
//go:embed rego/default_policy_module.rego
|
||||
var defaultPolicyModule string
|
||||
|
||||
//go:embed rego/default_policy.rego
|
||||
var defaultPolicyText string
|
||||
|
||||
// defaultPolicyTemplate is a template for the default policy
|
||||
var defaultPolicyTemplate = template.Must(template.New("policy").Parse(defaultPolicyText))
|
||||
|
||||
// PolicyRule is the metadata of the policy
|
||||
type PolicyRule struct {
|
||||
// ID of the policy rule
|
||||
@@ -65,18 +80,30 @@ type PolicyRule struct {
|
||||
|
||||
// Sources policy source groups
|
||||
Sources []string
|
||||
|
||||
// Bidirectional define if the rule is applicable in both directions, sources, and destinations
|
||||
Bidirectional bool
|
||||
|
||||
// Protocol type of the traffic
|
||||
Protocol PolicyRuleProtocolType
|
||||
|
||||
// Ports or it ranges list
|
||||
Ports []string
|
||||
}
|
||||
|
||||
// Copy returns a copy of a policy rule
|
||||
func (pm *PolicyRule) Copy() *PolicyRule {
|
||||
return &PolicyRule{
|
||||
ID: pm.ID,
|
||||
Name: pm.Name,
|
||||
Description: pm.Description,
|
||||
Enabled: pm.Enabled,
|
||||
Action: pm.Action,
|
||||
Destinations: pm.Destinations[:],
|
||||
Sources: pm.Sources[:],
|
||||
ID: pm.ID,
|
||||
Name: pm.Name,
|
||||
Description: pm.Description,
|
||||
Enabled: pm.Enabled,
|
||||
Action: pm.Action,
|
||||
Destinations: pm.Destinations[:],
|
||||
Sources: pm.Sources[:],
|
||||
Bidirectional: pm.Bidirectional,
|
||||
Protocol: pm.Protocol,
|
||||
Ports: pm.Ports[:],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +134,6 @@ type Policy struct {
|
||||
// Enabled status of the policy
|
||||
Enabled bool
|
||||
|
||||
// Query of Rego the policy
|
||||
Query string
|
||||
|
||||
// Rules of the policy
|
||||
Rules []*PolicyRule
|
||||
}
|
||||
@@ -121,7 +145,6 @@ func (p *Policy) Copy() *Policy {
|
||||
Name: p.Name,
|
||||
Description: p.Description,
|
||||
Enabled: p.Enabled,
|
||||
Query: p.Query,
|
||||
}
|
||||
for _, r := range p.Rules {
|
||||
c.Rules = append(c.Rules, r.Copy())
|
||||
@@ -134,214 +157,124 @@ func (p *Policy) EventMeta() map[string]any {
|
||||
return map[string]any{"name": p.Name}
|
||||
}
|
||||
|
||||
// UpdateQueryFromRules marshals policy rules to Rego string and set it to Query
|
||||
func (p *Policy) UpdateQueryFromRules() error {
|
||||
type templateVars struct {
|
||||
All []string
|
||||
Source []string
|
||||
Destination []string
|
||||
}
|
||||
queries := []string{}
|
||||
// UpgradeAndFix different version of policies to latest version
|
||||
func (p *Policy) UpgradeAndFix() {
|
||||
for _, r := range p.Rules {
|
||||
if !r.Enabled {
|
||||
continue
|
||||
// start migrate from version v0.20.3
|
||||
if r.Protocol == "" {
|
||||
r.Protocol = PolicyRuleProtocolALL
|
||||
}
|
||||
|
||||
buff := new(bytes.Buffer)
|
||||
input := templateVars{
|
||||
All: append(r.Destinations[:], r.Sources...),
|
||||
Source: r.Sources,
|
||||
Destination: r.Destinations,
|
||||
if r.Protocol == PolicyRuleProtocolALL && !r.Bidirectional {
|
||||
r.Bidirectional = true
|
||||
}
|
||||
if err := defaultPolicyTemplate.Execute(buff, input); err != nil {
|
||||
return status.Errorf(status.BadRequest, "failed to update policy query: %v", err)
|
||||
}
|
||||
queries = append(queries, buff.String())
|
||||
// -- v0.20.4
|
||||
}
|
||||
p.Query = strings.Join(queries, "\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// FirewallRule is a rule of the firewall.
|
||||
type FirewallRule struct {
|
||||
// PeerID of the peer
|
||||
PeerID string
|
||||
|
||||
// PeerIP of the peer
|
||||
PeerIP string
|
||||
|
||||
// Direction of the traffic
|
||||
Direction string
|
||||
Direction int
|
||||
|
||||
// Action of the traffic
|
||||
Action string
|
||||
|
||||
// Protocol of the traffic
|
||||
Protocol string
|
||||
|
||||
// Port of the traffic
|
||||
Port string
|
||||
|
||||
// id for internal purposes
|
||||
id string
|
||||
}
|
||||
|
||||
// parseFromRegoResult parses the Rego result to a FirewallRule.
|
||||
func (f *FirewallRule) parseFromRegoResult(value interface{}) error {
|
||||
object, ok := value.(map[string]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid Rego query eval result")
|
||||
}
|
||||
// getPeerConnectionResources for a given peer
|
||||
//
|
||||
// This function returns the list of peers and firewall rules that are applicable to a given peer.
|
||||
func (a *Account) getPeerConnectionResources(peerID string) ([]*Peer, []*FirewallRule) {
|
||||
generateResources, getAccumulatedResources := a.connResourcesGenerator()
|
||||
|
||||
peerID, ok := object["ID"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid Rego query eval result peer ID type")
|
||||
}
|
||||
|
||||
peerIP, ok := object["IP"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid Rego query eval result peer IP type")
|
||||
}
|
||||
|
||||
direction, ok := object["Direction"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid Rego query eval result peer direction type")
|
||||
}
|
||||
|
||||
action, ok := object["Action"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid Rego query eval result peer action type")
|
||||
}
|
||||
|
||||
port, ok := object["Port"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid Rego query eval result peer port type")
|
||||
}
|
||||
|
||||
f.PeerID = peerID
|
||||
f.PeerIP = peerIP
|
||||
f.Direction = direction
|
||||
f.Action = action
|
||||
f.Port = port
|
||||
|
||||
// NOTE: update this id each time when new field added
|
||||
f.id = peerID + peerIP + direction + action + port
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryPeersAndFwRulesByRego returns a list associated Peers and firewall rules list for this peer.
|
||||
func (a *Account) queryPeersAndFwRulesByRego(
|
||||
peerID string,
|
||||
queryNumber int,
|
||||
query string,
|
||||
) ([]*Peer, []*FirewallRule) {
|
||||
input := map[string]interface{}{
|
||||
"peer_id": peerID,
|
||||
"peers": a.Peers,
|
||||
"groups": a.Groups,
|
||||
}
|
||||
|
||||
stmt, err := rego.New(
|
||||
rego.Query("data.netbird.all"),
|
||||
rego.Module("netbird", defaultPolicyModule),
|
||||
rego.Module(fmt.Sprintf("netbird-%d", queryNumber), query),
|
||||
).PrepareForEval(context.TODO())
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get Rego query")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
evalResult, err := stmt.Eval(
|
||||
context.TODO(),
|
||||
rego.EvalInput(input),
|
||||
)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("eval Rego query")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if len(evalResult) == 0 || len(evalResult[0].Expressions) == 0 {
|
||||
log.Trace("empty Rego query eval result")
|
||||
return nil, nil
|
||||
}
|
||||
expressions, ok := evalResult[0].Expressions[0].Value.([]interface{})
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
dst := make(map[string]struct{})
|
||||
src := make(map[string]struct{})
|
||||
peers := make([]*Peer, 0, len(expressions))
|
||||
rules := make([]*FirewallRule, 0, len(expressions))
|
||||
for _, v := range expressions {
|
||||
rule := &FirewallRule{}
|
||||
if err := rule.parseFromRegoResult(v); err != nil {
|
||||
log.WithError(err).Error("parse Rego query eval result")
|
||||
continue
|
||||
}
|
||||
rules = append(rules, rule)
|
||||
switch rule.Direction {
|
||||
case "dst":
|
||||
if _, ok := dst[rule.PeerID]; ok {
|
||||
continue
|
||||
}
|
||||
dst[rule.PeerID] = struct{}{}
|
||||
case "src":
|
||||
if _, ok := src[rule.PeerID]; ok {
|
||||
continue
|
||||
}
|
||||
src[rule.PeerID] = struct{}{}
|
||||
default:
|
||||
log.WithField("direction", rule.Direction).Error("invalid direction")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
added := make(map[string]struct{})
|
||||
if _, ok := src[peerID]; ok {
|
||||
for id := range dst {
|
||||
if _, ok := added[id]; !ok && id != peerID {
|
||||
added[id] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := dst[peerID]; ok {
|
||||
for id := range src {
|
||||
if _, ok := added[id]; !ok && id != peerID {
|
||||
added[id] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for id := range added {
|
||||
peers = append(peers, a.Peers[id])
|
||||
}
|
||||
return peers, rules
|
||||
}
|
||||
|
||||
// getPeersByPolicy returns all peers that given peer has access to.
|
||||
func (a *Account) getPeersByPolicy(peerID string) (peers []*Peer, rules []*FirewallRule) {
|
||||
peersSeen := make(map[string]struct{})
|
||||
ruleSeen := make(map[string]struct{})
|
||||
for i, policy := range a.Policies {
|
||||
for _, policy := range a.Policies {
|
||||
if !policy.Enabled {
|
||||
continue
|
||||
}
|
||||
p, r := a.queryPeersAndFwRulesByRego(peerID, i, policy.Query)
|
||||
for _, peer := range p {
|
||||
if _, ok := peersSeen[peer.ID]; ok {
|
||||
|
||||
for _, rule := range policy.Rules {
|
||||
if !rule.Enabled {
|
||||
continue
|
||||
}
|
||||
peers = append(peers, peer)
|
||||
peersSeen[peer.ID] = struct{}{}
|
||||
}
|
||||
for _, rule := range r {
|
||||
if _, ok := ruleSeen[rule.id]; ok {
|
||||
continue
|
||||
|
||||
sourcePeers, peerInSources := getAllPeersFromGroups(a, rule.Sources, peerID)
|
||||
destinationPeers, peerInDestinations := getAllPeersFromGroups(a, rule.Destinations, peerID)
|
||||
|
||||
if rule.Bidirectional {
|
||||
if peerInSources {
|
||||
generateResources(rule, destinationPeers, firewallRuleDirectionIN)
|
||||
}
|
||||
if peerInDestinations {
|
||||
generateResources(rule, sourcePeers, firewallRuleDirectionOUT)
|
||||
}
|
||||
}
|
||||
|
||||
if peerInSources {
|
||||
generateResources(rule, destinationPeers, firewallRuleDirectionOUT)
|
||||
}
|
||||
|
||||
if peerInDestinations {
|
||||
generateResources(rule, sourcePeers, firewallRuleDirectionIN)
|
||||
}
|
||||
rules = append(rules, rule)
|
||||
ruleSeen[rule.id] = struct{}{}
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
return getAccumulatedResources()
|
||||
}
|
||||
|
||||
// connResourcesGenerator returns generator and accumulator function which returns the result of generator calls
|
||||
//
|
||||
// The generator function is used to generate the list of peers and firewall rules that are applicable to a given peer.
|
||||
// It safe to call the generator function multiple times for same peer and different rules no duplicates will be
|
||||
// generated. The accumulator function returns the result of all the generator calls.
|
||||
func (a *Account) connResourcesGenerator() (func(*PolicyRule, []*Peer, int), func() ([]*Peer, []*FirewallRule)) {
|
||||
rulesExists := make(map[string]struct{})
|
||||
peersExists := make(map[string]struct{})
|
||||
rules := make([]*FirewallRule, 0)
|
||||
peers := make([]*Peer, 0)
|
||||
return func(rule *PolicyRule, groupPeers []*Peer, direction int) {
|
||||
for _, peer := range groupPeers {
|
||||
if _, ok := peersExists[peer.ID]; !ok {
|
||||
peers = append(peers, peer)
|
||||
peersExists[peer.ID] = struct{}{}
|
||||
}
|
||||
|
||||
fwRule := FirewallRule{
|
||||
PeerIP: peer.IP.String(),
|
||||
Direction: direction,
|
||||
Action: string(rule.Action),
|
||||
Protocol: string(rule.Protocol),
|
||||
}
|
||||
|
||||
ruleID := fmt.Sprintf("%s%d", peer.ID+peer.IP.String(), direction)
|
||||
ruleID += string(rule.Protocol) + string(rule.Action) + strings.Join(rule.Ports, ",")
|
||||
if _, ok := rulesExists[ruleID]; ok {
|
||||
continue
|
||||
}
|
||||
rulesExists[ruleID] = struct{}{}
|
||||
|
||||
if len(rule.Ports) == 0 {
|
||||
rules = append(rules, &fwRule)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, port := range rule.Ports {
|
||||
addRule := fwRule
|
||||
addRule.Port = port
|
||||
rules = append(rules, &addRule)
|
||||
}
|
||||
}
|
||||
}, func() ([]*Peer, []*FirewallRule) {
|
||||
return peers, rules
|
||||
}
|
||||
}
|
||||
|
||||
// GetPolicy from the store
|
||||
@@ -475,3 +408,63 @@ func (am *DefaultAccountManager) savePolicy(account *Account, policy *Policy) (e
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func toProtocolFirewallRules(update []*FirewallRule) []*proto.FirewallRule {
|
||||
result := make([]*proto.FirewallRule, len(update))
|
||||
for i := range update {
|
||||
direction := proto.FirewallRule_IN
|
||||
if update[i].Direction == firewallRuleDirectionOUT {
|
||||
direction = proto.FirewallRule_OUT
|
||||
}
|
||||
action := proto.FirewallRule_ACCEPT
|
||||
if update[i].Action == string(PolicyTrafficActionDrop) {
|
||||
action = proto.FirewallRule_DROP
|
||||
}
|
||||
|
||||
protocol := proto.FirewallRule_UNKNOWN
|
||||
switch PolicyRuleProtocolType(update[i].Protocol) {
|
||||
case PolicyRuleProtocolALL:
|
||||
protocol = proto.FirewallRule_ALL
|
||||
case PolicyRuleProtocolTCP:
|
||||
protocol = proto.FirewallRule_TCP
|
||||
case PolicyRuleProtocolUDP:
|
||||
protocol = proto.FirewallRule_UDP
|
||||
case PolicyRuleProtocolICMP:
|
||||
protocol = proto.FirewallRule_ICMP
|
||||
}
|
||||
|
||||
result[i] = &proto.FirewallRule{
|
||||
PeerIP: update[i].PeerIP,
|
||||
Direction: direction,
|
||||
Action: action,
|
||||
Protocol: protocol,
|
||||
Port: update[i].Port,
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// getAllPeersFromGroups for given peer ID and list of groups
|
||||
//
|
||||
// Returns list of peers and boolean indicating if peer is in any of the groups
|
||||
func getAllPeersFromGroups(account *Account, groups []string, peerID string) ([]*Peer, bool) {
|
||||
peerInGroups := false
|
||||
filteredPeers := make([]*Peer, 0, len(groups))
|
||||
for _, g := range groups {
|
||||
group, ok := account.Groups[g]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, p := range group.Peers {
|
||||
peer := account.Peers[p]
|
||||
if peer.ID == peerID {
|
||||
peerInGroups = true
|
||||
continue
|
||||
}
|
||||
|
||||
filteredPeers = append(filteredPeers, peer)
|
||||
}
|
||||
}
|
||||
return filteredPeers, peerInGroups
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
@@ -11,262 +12,412 @@ import (
|
||||
func TestAccount_getPeersByPolicy(t *testing.T) {
|
||||
account := &Account{
|
||||
Peers: map[string]*Peer{
|
||||
"cfif97at2r9s73au3q00": {
|
||||
ID: "cfif97at2r9s73au3q00",
|
||||
"peerA": {
|
||||
ID: "peerA",
|
||||
IP: net.ParseIP("100.65.14.88"),
|
||||
},
|
||||
"cfif97at2r9s73au3q0g": {
|
||||
ID: "cfif97at2r9s73au3q0g",
|
||||
"peerB": {
|
||||
ID: "peerB",
|
||||
IP: net.ParseIP("100.65.80.39"),
|
||||
},
|
||||
"cfif97at2r9s73au3q10": {
|
||||
ID: "cfif97at2r9s73au3q10",
|
||||
"peerC": {
|
||||
ID: "peerC",
|
||||
IP: net.ParseIP("100.65.254.139"),
|
||||
},
|
||||
"cfif97at2r9s73au3q20": {
|
||||
ID: "cfif97at2r9s73au3q20",
|
||||
"peerD": {
|
||||
ID: "peerD",
|
||||
IP: net.ParseIP("100.65.62.5"),
|
||||
},
|
||||
"cfj4tiqt2r9s73dmeun0": {
|
||||
ID: "cfj4tiqt2r9s73dmeun0",
|
||||
"peerE": {
|
||||
ID: "peerE",
|
||||
IP: net.ParseIP("100.65.32.206"),
|
||||
},
|
||||
"cg7h032t2r9s73cg5fk0": {
|
||||
ID: "cg7h032t2r9s73cg5fk0",
|
||||
"peerF": {
|
||||
ID: "peerF",
|
||||
IP: net.ParseIP("100.65.250.202"),
|
||||
},
|
||||
"cgcnkj2t2r9s73cg5vv0": {
|
||||
ID: "cgcnkj2t2r9s73cg5vv0",
|
||||
"peerG": {
|
||||
ID: "peerG",
|
||||
IP: net.ParseIP("100.65.13.186"),
|
||||
},
|
||||
"cgcol4qt2r9s73cg601g": {
|
||||
ID: "cgcol4qt2r9s73cg601g",
|
||||
"peerH": {
|
||||
ID: "peerH",
|
||||
IP: net.ParseIP("100.65.29.55"),
|
||||
},
|
||||
},
|
||||
Groups: map[string]*Group{
|
||||
"cet9e92t2r9s7383ns20": {
|
||||
ID: "cet9e92t2r9s7383ns20",
|
||||
"GroupAll": {
|
||||
ID: "GroupAll",
|
||||
Name: "All",
|
||||
Peers: []string{
|
||||
"cfif97at2r9s73au3q0g",
|
||||
"cfif97at2r9s73au3q00",
|
||||
"cfif97at2r9s73au3q20",
|
||||
"cfif97at2r9s73au3q10",
|
||||
"cfj4tiqt2r9s73dmeun0",
|
||||
"cg7h032t2r9s73cg5fk0",
|
||||
"cgcnkj2t2r9s73cg5vv0",
|
||||
"cgcol4qt2r9s73cg601g",
|
||||
"peerB",
|
||||
"peerA",
|
||||
"peerD",
|
||||
"peerC",
|
||||
"peerE",
|
||||
"peerF",
|
||||
"peerG",
|
||||
"peerH",
|
||||
},
|
||||
},
|
||||
"cev90bat2r9s7383o150": {
|
||||
ID: "cev90bat2r9s7383o150",
|
||||
"GroupSwarm": {
|
||||
ID: "GroupSwarm",
|
||||
Name: "swarm",
|
||||
Peers: []string{
|
||||
"cfif97at2r9s73au3q0g",
|
||||
"cfif97at2r9s73au3q00",
|
||||
"cfif97at2r9s73au3q20",
|
||||
"cfj4tiqt2r9s73dmeun0",
|
||||
"cgcnkj2t2r9s73cg5vv0",
|
||||
"cgcol4qt2r9s73cg601g",
|
||||
"peerB",
|
||||
"peerA",
|
||||
"peerD",
|
||||
"peerE",
|
||||
"peerG",
|
||||
"peerH",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: map[string]*Rule{
|
||||
"cet9e92t2r9s7383ns2g": {
|
||||
ID: "cet9e92t2r9s7383ns2g",
|
||||
"RuleDefault": {
|
||||
ID: "RuleDefault",
|
||||
Name: "Default",
|
||||
Description: "This is a default rule that allows connections between all the resources",
|
||||
Source: []string{
|
||||
"cet9e92t2r9s7383ns20",
|
||||
"GroupAll",
|
||||
},
|
||||
Destination: []string{
|
||||
"cet9e92t2r9s7383ns20",
|
||||
"GroupAll",
|
||||
},
|
||||
},
|
||||
"cev90bat2r9s7383o15g": {
|
||||
ID: "cev90bat2r9s7383o15g",
|
||||
"RuleSwarm": {
|
||||
ID: "RuleSwarm",
|
||||
Name: "Swarm",
|
||||
Description: "",
|
||||
Source: []string{
|
||||
"cev90bat2r9s7383o150",
|
||||
"cet9e92t2r9s7383ns20",
|
||||
"GroupSwarm",
|
||||
"GroupAll",
|
||||
},
|
||||
Destination: []string{
|
||||
"cev90bat2r9s7383o150",
|
||||
"GroupSwarm",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
rule1, err := RuleToPolicy(account.Rules["cet9e92t2r9s7383ns2g"])
|
||||
rule1, err := RuleToPolicy(account.Rules["RuleDefault"])
|
||||
assert.NoError(t, err)
|
||||
|
||||
rule2, err := RuleToPolicy(account.Rules["cev90bat2r9s7383o15g"])
|
||||
rule2, err := RuleToPolicy(account.Rules["RuleSwarm"])
|
||||
assert.NoError(t, err)
|
||||
|
||||
account.Policies = append(account.Policies, rule1, rule2)
|
||||
|
||||
t.Run("check that all peers get map", func(t *testing.T) {
|
||||
for _, p := range account.Peers {
|
||||
peers, firewallRules := account.getPeersByPolicy(p.ID)
|
||||
peers, firewallRules := account.getPeerConnectionResources(p.ID)
|
||||
assert.GreaterOrEqual(t, len(peers), 2, "mininum number peers should present")
|
||||
assert.GreaterOrEqual(t, len(firewallRules), 2, "mininum number of firewall rules should present")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("check first peer map details", func(t *testing.T) {
|
||||
peers, firewallRules := account.getPeersByPolicy("cfif97at2r9s73au3q0g")
|
||||
peers, firewallRules := account.getPeerConnectionResources("peerB")
|
||||
assert.Len(t, peers, 7)
|
||||
assert.Contains(t, peers, account.Peers["cfif97at2r9s73au3q00"])
|
||||
assert.Contains(t, peers, account.Peers["cfif97at2r9s73au3q10"])
|
||||
assert.Contains(t, peers, account.Peers["cfif97at2r9s73au3q20"])
|
||||
assert.Contains(t, peers, account.Peers["cfj4tiqt2r9s73dmeun0"])
|
||||
assert.Contains(t, peers, account.Peers["cg7h032t2r9s73cg5fk0"])
|
||||
assert.Contains(t, peers, account.Peers["peerA"])
|
||||
assert.Contains(t, peers, account.Peers["peerC"])
|
||||
assert.Contains(t, peers, account.Peers["peerD"])
|
||||
assert.Contains(t, peers, account.Peers["peerE"])
|
||||
assert.Contains(t, peers, account.Peers["peerF"])
|
||||
|
||||
epectedFirewallRules := []*FirewallRule{
|
||||
{
|
||||
PeerID: "cfif97at2r9s73au3q00",
|
||||
PeerIP: "100.65.14.88",
|
||||
Direction: "src",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cfif97at2r9s73au3q00100.65.14.88srcaccept",
|
||||
},
|
||||
{
|
||||
PeerID: "cfif97at2r9s73au3q00",
|
||||
PeerIP: "100.65.14.88",
|
||||
Direction: "dst",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cfif97at2r9s73au3q00100.65.14.88dstaccept",
|
||||
},
|
||||
|
||||
{
|
||||
PeerID: "cfif97at2r9s73au3q0g",
|
||||
PeerIP: "100.65.80.39",
|
||||
Direction: "dst",
|
||||
Action: "accept",
|
||||
Port: "",
|
||||
id: "cfif97at2r9s73au3q0g100.65.80.39dstaccept",
|
||||
},
|
||||
{
|
||||
PeerID: "cfif97at2r9s73au3q0g",
|
||||
PeerIP: "100.65.80.39",
|
||||
Direction: "src",
|
||||
Action: "accept",
|
||||
Port: "",
|
||||
id: "cfif97at2r9s73au3q0g100.65.80.39srcaccept",
|
||||
},
|
||||
|
||||
{
|
||||
PeerID: "cfif97at2r9s73au3q10",
|
||||
PeerIP: "100.65.254.139",
|
||||
Direction: "dst",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cfif97at2r9s73au3q10100.65.254.139dstaccept",
|
||||
},
|
||||
{
|
||||
PeerID: "cfif97at2r9s73au3q10",
|
||||
PeerIP: "100.65.254.139",
|
||||
Direction: "src",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cfif97at2r9s73au3q10100.65.254.139srcaccept",
|
||||
},
|
||||
|
||||
{
|
||||
PeerID: "cfif97at2r9s73au3q20",
|
||||
PeerIP: "100.65.62.5",
|
||||
Direction: "dst",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cfif97at2r9s73au3q20100.65.62.5dstaccept",
|
||||
},
|
||||
{
|
||||
PeerID: "cfif97at2r9s73au3q20",
|
||||
PeerIP: "100.65.62.5",
|
||||
Direction: "src",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cfif97at2r9s73au3q20100.65.62.5srcaccept",
|
||||
},
|
||||
|
||||
{
|
||||
PeerID: "cfj4tiqt2r9s73dmeun0",
|
||||
PeerIP: "100.65.32.206",
|
||||
Direction: "dst",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cfj4tiqt2r9s73dmeun0100.65.32.206dstaccept",
|
||||
},
|
||||
{
|
||||
PeerID: "cfj4tiqt2r9s73dmeun0",
|
||||
PeerIP: "100.65.32.206",
|
||||
Direction: "src",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cfj4tiqt2r9s73dmeun0100.65.32.206srcaccept",
|
||||
},
|
||||
|
||||
{
|
||||
PeerID: "cg7h032t2r9s73cg5fk0",
|
||||
PeerIP: "100.65.250.202",
|
||||
Direction: "dst",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cg7h032t2r9s73cg5fk0100.65.250.202dstaccept",
|
||||
},
|
||||
{
|
||||
PeerID: "cg7h032t2r9s73cg5fk0",
|
||||
PeerIP: "100.65.250.202",
|
||||
Direction: "src",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cg7h032t2r9s73cg5fk0100.65.250.202srcaccept",
|
||||
},
|
||||
|
||||
{
|
||||
PeerID: "cgcnkj2t2r9s73cg5vv0",
|
||||
PeerIP: "100.65.13.186",
|
||||
Direction: "dst",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cgcnkj2t2r9s73cg5vv0100.65.13.186dstaccept",
|
||||
},
|
||||
{
|
||||
PeerID: "cgcnkj2t2r9s73cg5vv0",
|
||||
PeerIP: "100.65.13.186",
|
||||
Direction: "src",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cgcnkj2t2r9s73cg5vv0100.65.13.186srcaccept",
|
||||
},
|
||||
|
||||
{
|
||||
PeerID: "cgcol4qt2r9s73cg601g",
|
||||
PeerIP: "100.65.29.55",
|
||||
Direction: "dst",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cgcol4qt2r9s73cg601g100.65.29.55dstaccept",
|
||||
},
|
||||
{
|
||||
PeerID: "cgcol4qt2r9s73cg601g",
|
||||
PeerIP: "100.65.29.55",
|
||||
Direction: "src",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
id: "cgcol4qt2r9s73cg601g100.65.29.55srcaccept",
|
||||
},
|
||||
}
|
||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
||||
slices.SortFunc(firewallRules, func(a, b *FirewallRule) bool {
|
||||
return a.PeerID < b.PeerID
|
||||
})
|
||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
||||
slices.SortFunc(firewallRules, sortFunc())
|
||||
for i := range firewallRules {
|
||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccount_getPeersByPolicyDirect(t *testing.T) {
|
||||
account := &Account{
|
||||
Peers: map[string]*Peer{
|
||||
"peerA": {
|
||||
ID: "peerA",
|
||||
IP: net.ParseIP("100.65.14.88"),
|
||||
},
|
||||
"peerB": {
|
||||
ID: "peerB",
|
||||
IP: net.ParseIP("100.65.80.39"),
|
||||
},
|
||||
"peerC": {
|
||||
ID: "peerC",
|
||||
IP: net.ParseIP("100.65.254.139"),
|
||||
},
|
||||
},
|
||||
Groups: map[string]*Group{
|
||||
"GroupAll": {
|
||||
ID: "GroupAll",
|
||||
Name: "All",
|
||||
Peers: []string{
|
||||
"peerB",
|
||||
"peerA",
|
||||
"peerC",
|
||||
},
|
||||
},
|
||||
"GroupSwarm": {
|
||||
ID: "GroupSwarm",
|
||||
Name: "swarm",
|
||||
Peers: []string{
|
||||
"peerB",
|
||||
},
|
||||
},
|
||||
"peerF": {
|
||||
ID: "peerF",
|
||||
Name: "dmz",
|
||||
Peers: []string{
|
||||
"peerC",
|
||||
},
|
||||
},
|
||||
},
|
||||
Rules: map[string]*Rule{
|
||||
"RuleDefault": {
|
||||
ID: "RuleDefault",
|
||||
Name: "Default",
|
||||
Disabled: true,
|
||||
Description: "This is a default rule that allows connections between all the resources",
|
||||
Source: []string{
|
||||
"GroupAll",
|
||||
},
|
||||
Destination: []string{
|
||||
"GroupAll",
|
||||
},
|
||||
},
|
||||
"RuleSwarm": {
|
||||
ID: "RuleSwarm",
|
||||
Name: "Swarm",
|
||||
Description: "",
|
||||
Source: []string{
|
||||
"GroupSwarm",
|
||||
},
|
||||
Destination: []string{
|
||||
"peerF",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
rule1, err := RuleToPolicy(account.Rules["RuleDefault"])
|
||||
assert.NoError(t, err)
|
||||
|
||||
rule2, err := RuleToPolicy(account.Rules["RuleSwarm"])
|
||||
assert.NoError(t, err)
|
||||
|
||||
account.Policies = append(account.Policies, rule1, rule2)
|
||||
|
||||
t.Run("check first peer map", func(t *testing.T) {
|
||||
peers, firewallRules := account.getPeerConnectionResources("peerB")
|
||||
assert.Contains(t, peers, account.Peers["peerC"])
|
||||
|
||||
epectedFirewallRules := []*FirewallRule{
|
||||
{
|
||||
PeerIP: "100.65.254.139",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
},
|
||||
{
|
||||
PeerIP: "100.65.254.139",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
},
|
||||
}
|
||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
||||
slices.SortFunc(firewallRules, sortFunc())
|
||||
for i := range firewallRules {
|
||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("check second peer map", func(t *testing.T) {
|
||||
peers, firewallRules := account.getPeerConnectionResources("peerC")
|
||||
assert.Contains(t, peers, account.Peers["peerB"])
|
||||
|
||||
epectedFirewallRules := []*FirewallRule{
|
||||
{
|
||||
PeerIP: "100.65.80.39",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
},
|
||||
{
|
||||
PeerIP: "100.65.80.39",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
},
|
||||
}
|
||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
||||
slices.SortFunc(firewallRules, sortFunc())
|
||||
for i := range firewallRules {
|
||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
||||
}
|
||||
})
|
||||
|
||||
account.Policies[1].Rules[0].Bidirectional = false
|
||||
|
||||
t.Run("check first peer map directional only", func(t *testing.T) {
|
||||
peers, firewallRules := account.getPeerConnectionResources("peerB")
|
||||
assert.Contains(t, peers, account.Peers["peerC"])
|
||||
|
||||
epectedFirewallRules := []*FirewallRule{
|
||||
{
|
||||
PeerIP: "100.65.254.139",
|
||||
Direction: firewallRuleDirectionOUT,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
},
|
||||
}
|
||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
||||
slices.SortFunc(firewallRules, sortFunc())
|
||||
for i := range firewallRules {
|
||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("check second peer map directional only", func(t *testing.T) {
|
||||
peers, firewallRules := account.getPeerConnectionResources("peerC")
|
||||
assert.Contains(t, peers, account.Peers["peerB"])
|
||||
|
||||
epectedFirewallRules := []*FirewallRule{
|
||||
{
|
||||
PeerIP: "100.65.80.39",
|
||||
Direction: firewallRuleDirectionIN,
|
||||
Action: "accept",
|
||||
Protocol: "all",
|
||||
Port: "",
|
||||
},
|
||||
}
|
||||
assert.Len(t, firewallRules, len(epectedFirewallRules))
|
||||
slices.SortFunc(epectedFirewallRules, sortFunc())
|
||||
slices.SortFunc(firewallRules, sortFunc())
|
||||
for i := range firewallRules {
|
||||
assert.Equal(t, epectedFirewallRules[i], firewallRules[i])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func sortFunc() func(a *FirewallRule, b *FirewallRule) bool {
|
||||
return func(a, b *FirewallRule) bool {
|
||||
return a.PeerIP+fmt.Sprintf("%d", a.Direction) < b.PeerIP+fmt.Sprintf("%d", b.Direction)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package netbird
|
||||
|
||||
all[rule] {
|
||||
is_peer_in_any_group([{{range $i, $e := .All}}{{if $i}},{{end}}"{{$e}}"{{end}}])
|
||||
rule := {
|
||||
{{range $i, $e := .Destination}}rules_from_group("{{$e}}", "dst", "accept", ""),{{end}}
|
||||
{{range $i, $e := .Source}}rules_from_group("{{$e}}", "src", "accept", ""),{{end}}
|
||||
}[_][_]
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package netbird
|
||||
|
||||
import future.keywords.if
|
||||
import future.keywords.in
|
||||
import future.keywords.contains
|
||||
|
||||
# get_rule builds a netbird rule object from given parameters
|
||||
get_rule(peer_id, direction, action, port) := rule if {
|
||||
peer := input.peers[_]
|
||||
peer.ID == peer_id
|
||||
rule := {
|
||||
"ID": peer.ID,
|
||||
"IP": peer.IP,
|
||||
"Direction": direction,
|
||||
"Action": action,
|
||||
"Port": port,
|
||||
}
|
||||
}
|
||||
|
||||
# netbird_rules_from_group returns a list of netbird rules for a given group_id
|
||||
rules_from_group(group_id, direction, action, port) := rules if {
|
||||
group := input.groups[_]
|
||||
group.ID == group_id
|
||||
rules := [get_rule(peer, direction, action, port) | peer := group.Peers[_]]
|
||||
}
|
||||
|
||||
# is_peer_in_any_group checks that input peer present at least in one group
|
||||
is_peer_in_any_group(groups) := count([group_id]) > 0 if {
|
||||
group_id := groups[_]
|
||||
group := input.groups[_]
|
||||
group.ID == group_id
|
||||
peer := group.Peers[_]
|
||||
peer == input.peer_id
|
||||
}
|
||||
@@ -911,8 +911,6 @@ func TestGetNetworkMap_RouteSync(t *testing.T) {
|
||||
newPolicy.Name = "peer1 only"
|
||||
newPolicy.Rules[0].Sources = []string{newGroup.ID}
|
||||
newPolicy.Rules[0].Destinations = []string{newGroup.ID}
|
||||
err = newPolicy.UpdateQueryFromRules()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = am.SavePolicy(account.Id, userID, newPolicy)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -67,13 +67,15 @@ func (r *Rule) ToPolicyRule() *PolicyRule {
|
||||
return nil
|
||||
}
|
||||
return &PolicyRule{
|
||||
ID: r.ID,
|
||||
Name: r.Name,
|
||||
Enabled: !r.Disabled,
|
||||
Description: r.Description,
|
||||
Action: PolicyTrafficActionAccept,
|
||||
Destinations: r.Destination,
|
||||
Sources: r.Source,
|
||||
ID: r.ID,
|
||||
Name: r.Name,
|
||||
Enabled: !r.Disabled,
|
||||
Description: r.Description,
|
||||
Destinations: r.Destination,
|
||||
Sources: r.Source,
|
||||
Bidirectional: true,
|
||||
Protocol: PolicyRuleProtocolALL,
|
||||
Action: PolicyTrafficActionAccept,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,15 +84,11 @@ func RuleToPolicy(rule *Rule) (*Policy, error) {
|
||||
if rule == nil {
|
||||
return nil, fmt.Errorf("rule is empty")
|
||||
}
|
||||
policy := &Policy{
|
||||
return &Policy{
|
||||
ID: rule.ID,
|
||||
Name: rule.Name,
|
||||
Description: rule.Description,
|
||||
Enabled: !rule.Disabled,
|
||||
Rules: []*PolicyRule{rule.ToPolicyRule()},
|
||||
}
|
||||
if err := policy.UpdateQueryFromRules(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return policy, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user