Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cilium: Added support to generate icmp rules #439

Merged
merged 4 commits into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/cluster/k8sClientHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ func GetServicesFromK8sClient() []types.Service {
k8sService.Labels = append(k8sService.Labels, k+"="+v)
}

for _, ip := range svc.Spec.ExternalIPs {
k8sService.ExternalIPs = append(k8sService.ExternalIPs, ip)
}

for _, port := range svc.Spec.Ports {
k8sService.ClusterIP = string(svc.Spec.ClusterIP)
k8sService.Protocol = string(port.Protocol)
Expand Down
2 changes: 1 addition & 1 deletion src/config/configManager.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func LoadConfigFromFile() {
NetworkPolicyDir: viper.GetString("application.network.network-policy-dir"),

NetPolicyTypes: 3,
NetPolicyRuleTypes: 511,
NetPolicyRuleTypes: 1023,
NetPolicyCIDRBits: 32,

NetLogFilters: []types.NetworkLogFilter{},
Expand Down
43 changes: 37 additions & 6 deletions src/libs/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,30 @@ var GitBranch string
var BuildDate string
var Version string

const (
IPProtoUnknown = -1
IPProtocolICMP = 1
IPProtocolTCP = 6
IPProtocolUDP = 17
IPProtocolICMPv6 = 58
IPProtocolSCTP = 132
)

var protocolMap = map[int]string{
IPProtoUnknown: "Unknown",
IPProtocolICMP: "ICMP",
IPProtocolTCP: "TCP",
IPProtocolUDP: "UDP",
IPProtocolICMPv6: "ICMPv6",
IPProtocolSCTP: "SCTP",
}

// Array for ICMP type which can be considered as ICMP reply packets.
// TODO: Identity all the ICMP reply types
var ICMPReplyType = []int{
0, // EchoReply
}

func printBuildDetails() {
if GitCommit == "" {
return
Expand Down Expand Up @@ -210,14 +234,21 @@ func GetExternalIPAddr() string {
}

func GetProtocol(protocol int) string {
protocolMap := map[int]string{
1: "ICMP",
6: "TCP",
17: "UDP",
132: "STCP",
return protocolMap[protocol]
}

func IsICMP(protocol int) bool {
if protocol == IPProtocolICMP || protocol == IPProtocolICMPv6 {
return true
}
return false
}

return protocolMap[protocol]
func IsReplyICMP(icmpType int) bool {
if ContainsElement(ICMPReplyType, icmpType) {
return true
}
return false
}

// ============ //
Expand Down
131 changes: 107 additions & 24 deletions src/networkpolicy/deduplicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package networkpolicy
import (
"sort"
"strings"
"time"

"github.com/accuknox/auto-policy-discovery/src/libs"
types "github.com/accuknox/auto-policy-discovery/src/types"
Expand Down Expand Up @@ -344,9 +345,9 @@ func UpdateHTTP(newPolicy types.KnoxNetworkPolicy, existingPolicies []types.Knox
func UpdateToPorts(newPolicy types.KnoxNetworkPolicy, existingPolicies []types.KnoxNetworkPolicy) (types.KnoxNetworkPolicy, bool) {
// case 1: if there is no latest, policy is new one
latestPolicies := []types.KnoxNetworkPolicy{}
if newPolicy.Metadata["rule"] == "toCIDRs+toPorts" {
if strings.Contains(newPolicy.Metadata["rule"], "toCIDRs") {
latestPolicies = GetLatestCIDRPolicy(existingPolicies, newPolicy)
} else if newPolicy.Metadata["rule"] == "toFQDNs+toPorts" {
} else if strings.Contains(newPolicy.Metadata["rule"], "toFQDNs") {
latestPolicies = GetLatestFQDNPolicy(existingPolicies, newPolicy)
} else {
return newPolicy, true
Expand All @@ -357,31 +358,46 @@ func UpdateToPorts(newPolicy types.KnoxNetworkPolicy, existingPolicies []types.K
}

newToPorts := []types.SpecPort{}
newICMPs := []types.SpecICMP{}
if newPolicy.Metadata["type"] == "egress" {
newToPorts = newPolicy.Spec.Egress[0].ToPorts
newICMPs = newPolicy.Spec.Egress[0].ICMPs
} else {
newToPorts = newPolicy.Spec.Ingress[0].ToPorts
newICMPs = newPolicy.Spec.Ingress[0].ICMPs
}

updated := false

for _, latestPolicy := range latestPolicies {
existToPorts := []types.SpecPort{}
existICMPs := []types.SpecICMP{}
if newPolicy.Metadata["type"] == "egress" {
existToPorts = latestPolicy.Spec.Egress[0].ToPorts
existICMPs = latestPolicy.Spec.Egress[0].ICMPs
} else {
existToPorts = latestPolicy.Spec.Ingress[0].ToPorts
existICMPs = latestPolicy.Spec.Ingress[0].ICMPs
}

includeAllRules := true
for _, rule := range newToPorts {
if !libs.ContainsElement(existToPorts, rule) {
includeAllRules = false
includedAllPortRules := true
for _, port := range newToPorts {
if !libs.ContainsElement(existToPorts, port) {
includedAllPortRules = false
break
}
}

// case 2: policy has toPorts, which are all includes in latest one
if includeAllRules {
includedAllICMPRules := true
for _, icmp := range newICMPs {
if !libs.ContainsElement(existICMPs, icmp) {
includedAllICMPRules = false
break
}
}

// case 2: policy has toPorts & icmps, which are all included in latest one
if includedAllPortRules && includedAllICMPRules {
// case 2-1: policy has the lower selector count? outdated
if len(newPolicy.Spec.Selector.MatchLabels) < len(latestPolicy.Spec.Selector.MatchLabels) {
updateOutdatedPolicy(latestPolicy, &newPolicy)
Expand All @@ -391,10 +407,20 @@ func UpdateToPorts(newPolicy types.KnoxNetworkPolicy, existingPolicies []types.K
continue // next existPolicy
}

// case 3: policy has toPorts, latest has toPorts or no toPorts --> move to new policy
for _, toPort := range existToPorts {
if !libs.ContainsElement(newToPorts, toPort) {
newToPorts = append(newToPorts, toPort)
// case 3: policy has toPorts or icmps which are not included in latest one
if !includedAllPortRules {
for _, toPort := range existToPorts {
if !libs.ContainsElement(newToPorts, toPort) {
newToPorts = append(newToPorts, toPort)
}
}
}

if !includedAllICMPRules {
for _, icmp := range existICMPs {
if !libs.ContainsElement(newICMPs, icmp) {
newICMPs = append(newICMPs, icmp)
}
}
}

Expand All @@ -407,10 +433,11 @@ func UpdateToPorts(newPolicy types.KnoxNetworkPolicy, existingPolicies []types.K
if updated {
if newPolicy.Metadata["type"] == "egress" {
newPolicy.Spec.Egress[0].ToPorts = newToPorts
newPolicy.Spec.Egress[0].ICMPs = newICMPs
} else {
newPolicy.Spec.Ingress[0].ToPorts = newToPorts
newPolicy.Spec.Ingress[0].ICMPs = newICMPs
}

return newPolicy, true
}

Expand All @@ -424,39 +451,54 @@ func UpdateMatchLabels(newPolicy types.KnoxNetworkPolicy, existingPolicies []typ
return newPolicy, true
}

newICMPs := []types.SpecICMP{}
newToPorts := []types.SpecPort{}
newTargetLabelsCount := 0
if newPolicy.Metadata["type"] == "egress" {
newToPorts = newPolicy.Spec.Egress[0].ToPorts
newICMPs = newPolicy.Spec.Egress[0].ICMPs
newTargetLabelsCount = len(newPolicy.Spec.Egress[0].MatchLabels)
} else {
newToPorts = newPolicy.Spec.Ingress[0].ToPorts
newICMPs = newPolicy.Spec.Egress[0].ICMPs
newTargetLabelsCount = len(newPolicy.Spec.Ingress[0].MatchLabels)
}

updated := false

for _, latestPolicy := range latestPolicies {
existToPorts := []types.SpecPort{}
existICMPs := []types.SpecICMP{}
existTargetLabelsCount := 0

if newPolicy.Metadata["type"] == "egress" {
existToPorts = latestPolicy.Spec.Egress[0].ToPorts
existICMPs = latestPolicy.Spec.Egress[0].ICMPs
existTargetLabelsCount = len(latestPolicy.Spec.Egress[0].MatchLabels)
} else {
existToPorts = latestPolicy.Spec.Ingress[0].ToPorts
existICMPs = latestPolicy.Spec.Ingress[0].ICMPs
existTargetLabelsCount = len(latestPolicy.Spec.Ingress[0].MatchLabels)
}

includeAllRules := true
includedAllPortRules := true
for _, rule := range newToPorts {
if !libs.ContainsElement(existToPorts, rule) {
includeAllRules = false
includedAllPortRules = false
break
}
}

// case 2: policy has toPorts, which are all includes in latest one
if includeAllRules {
includedAllICMPRules := true
for _, icmp := range newICMPs {
if !libs.ContainsElement(existICMPs, icmp) {
includedAllICMPRules = false
break
}
}

// case 2: policy has toPorts & icmps, which are all included in latest one
if includedAllPortRules && includedAllICMPRules {
// case 2-1: policy has the lower selector count? outdated
if len(newPolicy.Spec.Selector.MatchLabels) < len(latestPolicy.Spec.Selector.MatchLabels) ||
newTargetLabelsCount < existTargetLabelsCount {
Expand All @@ -468,10 +510,20 @@ func UpdateMatchLabels(newPolicy types.KnoxNetworkPolicy, existingPolicies []typ
continue // next existPolicy
}

// case 3: policy has toPorts, latest has toPorts or no toPorts --> move to new policy
for _, toPort := range existToPorts {
if !libs.ContainsElement(newToPorts, toPort) {
newToPorts = append(newToPorts, toPort)
// case 3: policy has toPorts or icmps which are not included in latest one
if !includedAllPortRules {
for _, toPort := range existToPorts {
if !libs.ContainsElement(newToPorts, toPort) {
newToPorts = append(newToPorts, toPort)
}
}
}

if !includedAllICMPRules {
for _, icmp := range existICMPs {
if !libs.ContainsElement(newICMPs, icmp) {
newICMPs = append(newICMPs, icmp)
}
}
}

Expand All @@ -484,8 +536,9 @@ func UpdateMatchLabels(newPolicy types.KnoxNetworkPolicy, existingPolicies []typ
if updated {
if newPolicy.Metadata["type"] == "egress" {
newPolicy.Spec.Egress[0].ToPorts = newToPorts
newPolicy.Spec.Egress[0].ICMPs = newICMPs
} else {
newPolicy.Spec.Ingress[0].ToPorts = newToPorts
newPolicy.Spec.Ingress[0].ICMPs = newICMPs
}

return newPolicy, true
Expand Down Expand Up @@ -747,6 +800,30 @@ func updateExistCIDRtoNewFQDN(existingPolicies []types.KnoxNetworkPolicy, newPol
}
}

if len(existCIDR.Spec.Egress[0].ICMPs) > 0 {
// if cidr has ICMPs also, check duplication as well
cidrICMPs := existCIDR.Spec.Egress[0].ICMPs
fqdnICMPs := fqdnPolicy.Spec.Egress[0].ICMPs
if fqdnICMPs == nil {
fqdnICMPs = []types.SpecICMP{}
}

// move cidr's ICMPs -> fqdn's ICMPs
for _, icmp := range cidrICMPs {
if !libs.ContainsElement(fqdnICMPs, icmp) {
fqdnICMPs = append(fqdnICMPs, icmp)
}
}

// updated fqdn -> newPolicies
fqdnPolicy.Spec.Egress[0].ICMPs = fqdnICMPs
for i, exist := range newPolicies {
if fqdnPolicy.Metadata["name"] == exist.Metadata["name"] {
newPolicies[i] = fqdnPolicy
}
}
}

libs.UpdateOutdatedNetworkPolicy(CfgDB, existCIDR.Metadata["name"], fqdnPolicy.Metadata["name"])
}
}
Expand Down Expand Up @@ -815,7 +892,7 @@ func UpdateDuplicatedPolicy(existingPolicies []types.KnoxNetworkPolicy, discover
}

// step 5: update existing FQDN+toPorts rules: egress
if strings.Contains(policy.Metadata["rule"], "toFQDNs") && policy.Metadata["rule"] == "egress" {
if strings.Contains(policy.Metadata["rule"], "toFQDNs") && policy.Metadata["type"] == "egress" {
updatedPolicy, updated := UpdateToPorts(namedPolicy, existingPolicies)
if updated {
namedPolicy = updatedPolicy
Expand All @@ -831,13 +908,19 @@ func UpdateDuplicatedPolicy(existingPolicies []types.KnoxNetworkPolicy, discover
}

// step 7: update existing Entities rules: egress
if strings.Contains(policy.Metadata["rule"], "toServices") && policy.Metadata["rule"] == "egress" {
if strings.Contains(policy.Metadata["rule"], "toServices") && policy.Metadata["type"] == "egress" {
updatedPolicy, updated := UpdateService(namedPolicy, existingPolicies)
if updated {
namedPolicy = updatedPolicy
}
}

// step 8: update status
namedPolicy.Metadata["status"] = "latest"

// step 9: update generated time
namedPolicy.GeneratedTime = time.Now().Unix()

newPolicies = append(newPolicies, namedPolicy)
}

Expand Down
Loading