mirror of
https://github.com/jsiebens/ionscale.git
synced 2026-03-31 15:07:49 +01:00
feat: add support for protocol in acl rules
This commit is contained in:
+56
-3
@@ -39,6 +39,7 @@ type ACLPolicy struct {
|
||||
|
||||
type ACL struct {
|
||||
Action string `json:"action"`
|
||||
Proto string `json:"proto"`
|
||||
Src []string `json:"src"`
|
||||
Dst []string `json:"dst"`
|
||||
}
|
||||
@@ -254,7 +255,7 @@ func (a ACLPolicy) NodeCapabilities(m *Machine) []tailcfg.NodeCapability {
|
||||
func (a ACLPolicy) BuildFilterRules(srcs []Machine, dst *Machine) []tailcfg.FilterRule {
|
||||
var rules = make([]tailcfg.FilterRule, 0)
|
||||
|
||||
appendRules := func(rules []tailcfg.FilterRule, src []string, destPorts []tailcfg.NetPortRange, u *User) []tailcfg.FilterRule {
|
||||
appendRules := func(rules []tailcfg.FilterRule, proto string, src []string, destPorts []tailcfg.NetPortRange, u *User) []tailcfg.FilterRule {
|
||||
var allSrcIPsSet = &StringSet{}
|
||||
for _, alias := range src {
|
||||
for _, src := range srcs {
|
||||
@@ -272,16 +273,17 @@ func (a ACLPolicy) BuildFilterRules(srcs []Machine, dst *Machine) []tailcfg.Filt
|
||||
return append(rules, tailcfg.FilterRule{
|
||||
SrcIPs: allSrcIPs,
|
||||
DstPorts: destPorts,
|
||||
IPProto: parseProtocol(proto),
|
||||
})
|
||||
}
|
||||
|
||||
for _, acl := range a.ACLs {
|
||||
selfDestPorts, allDestPorts := a.expandMachineToDstPorts(dst, acl.Dst)
|
||||
if len(selfDestPorts) != 0 {
|
||||
rules = appendRules(rules, acl.Src, selfDestPorts, &dst.User)
|
||||
rules = appendRules(rules, acl.Proto, acl.Src, selfDestPorts, &dst.User)
|
||||
}
|
||||
if len(allDestPorts) != 0 {
|
||||
rules = appendRules(rules, acl.Src, allDestPorts, nil)
|
||||
rules = appendRules(rules, acl.Proto, acl.Src, allDestPorts, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,6 +506,57 @@ func (ACLPolicy) GormDBDataType(db *gorm.DB, field *schema.Field) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
const (
|
||||
protocolICMP = 1 // Internet Control Message
|
||||
protocolIGMP = 2 // Internet Group Management
|
||||
protocolIPv4 = 4 // IPv4 encapsulation
|
||||
protocolTCP = 6 // Transmission Control
|
||||
protocolEGP = 8 // Exterior Gateway Protocol
|
||||
protocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
|
||||
protocolUDP = 17 // User Datagram
|
||||
protocolGRE = 47 // Generic Routing Encapsulation
|
||||
protocolESP = 50 // Encap Security Payload
|
||||
protocolAH = 51 // Authentication Header
|
||||
protocolIPv6ICMP = 58 // ICMP for IPv6
|
||||
protocolSCTP = 132 // Stream Control Transmission Protocol
|
||||
)
|
||||
|
||||
func parseProtocol(protocol string) []int {
|
||||
switch protocol {
|
||||
case "":
|
||||
return nil
|
||||
case "igmp":
|
||||
return []int{protocolIGMP}
|
||||
case "ipv4", "ip-in-ip":
|
||||
return []int{protocolIPv4}
|
||||
case "tcp":
|
||||
return []int{protocolTCP}
|
||||
case "egp":
|
||||
return []int{protocolEGP}
|
||||
case "igp":
|
||||
return []int{protocolIGP}
|
||||
case "udp":
|
||||
return []int{protocolUDP}
|
||||
case "gre":
|
||||
return []int{protocolGRE}
|
||||
case "esp":
|
||||
return []int{protocolESP}
|
||||
case "ah":
|
||||
return []int{protocolAH}
|
||||
case "sctp":
|
||||
return []int{protocolSCTP}
|
||||
case "icmp":
|
||||
return []int{protocolICMP, protocolIPv6ICMP}
|
||||
|
||||
default:
|
||||
n, err := strconv.Atoi(protocol)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return []int{n}
|
||||
}
|
||||
}
|
||||
|
||||
type StringSet struct {
|
||||
items map[string]bool
|
||||
}
|
||||
|
||||
@@ -155,6 +155,60 @@ func TestACLPolicy_BuildFilterRulesWildcards(t *testing.T) {
|
||||
assert.Equal(t, expectedRules, actualRules)
|
||||
}
|
||||
|
||||
func TestACLPolicy_BuildFilterRulesProto(t *testing.T) {
|
||||
p1 := createMachine("john@example.com")
|
||||
p2 := createMachine("jane@example.com")
|
||||
|
||||
policy := ACLPolicy{
|
||||
ACLs: []ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Src: []string{"*"},
|
||||
Dst: []string{"*:22"},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Src: []string{"*"},
|
||||
Dst: []string{"*:*"},
|
||||
Proto: "igmp",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
dst := createMachine("john@example.com")
|
||||
|
||||
actualRules := policy.BuildFilterRules([]Machine{*p1, *p2}, dst)
|
||||
expectedRules := []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"*"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{
|
||||
IP: "*",
|
||||
Ports: tailcfg.PortRange{
|
||||
First: 22,
|
||||
Last: 22,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
SrcIPs: []string{"*"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{
|
||||
IP: "*",
|
||||
Ports: tailcfg.PortRange{
|
||||
First: 0,
|
||||
Last: 65535,
|
||||
},
|
||||
},
|
||||
},
|
||||
IPProto: []int{protocolIGMP},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedRules, actualRules)
|
||||
}
|
||||
|
||||
func TestACLPolicy_BuildFilterRulesWithGroups(t *testing.T) {
|
||||
p1 := createMachine("jane@example.com")
|
||||
p2 := createMachine("nick@example.com")
|
||||
|
||||
Reference in New Issue
Block a user