kubernetes-sigs / network-policy-api

This repo addresses further work involving Kubernetes network security beyond the initial NetworkPolicy resource
Apache License 2.0
50 stars 28 forks source link

[Policy Assistant] calculate all allowed connections in a cluster #221

Open huntergregory opened 2 months ago

huntergregory commented 2 months ago

Parent issue: #150

Goal

For all the Deployments and DaemonSets in a cluster, calculate the set of allowed connections given a set of policies.

Current Functionality

Check whether traffic is allowed/denied for the specified source, destination, and port/protocol.

image

Proposed New Feature

Produce JSON of all allowed connections and the effective policy rules causing this.

Here is one idea for the format (let me put this in a PR):

{
    "Connections": [
        {
            "From": "10.0.0.0/28",
            "To": "ns-dev/daemonset/backend",
            "AllowedTraffic": {
                "TCPPorts": "all"
            },
            "EffectivePolicyRules": {
                "Ingress": {
                    "ANPPassed": [
                        {
                            "PolicyKey": "default/anp1",
                            "Priority": 1,
                            "RuleNumber": 9,
                            "Rule": "dev-pass-on-external-tcp",
                            "TCPPorts": "all"
                        }
                    ],
                    "ANPDenied": [
                        {
                            "PolicyKey": "default/anp1",
                            "Priority": 1,
                            "RuleNumber": 10,
                            "Rule": "deny-external",
                            "UDPPorts": "all",
                            "OtherPorts": "all"
                        }
                    ],
                    "NPv1Allowed": [
                        {
                            "PolicyKey": "ns-dev/allow-all",
                            "TCPPorts": "all"
                        }
                    ]
                }
            }
        },
        {
            "From": "ns-dev/deployment/frontend",
            "To": "ns-dev/daemonset/backend",
            "AllowedTraffic": {
                "TCPPorts": "80",
                "UDPPorts": "53,80"
            },
            "EffectivePolicyRules": {
                "Ingress": {
                    "ANPAllowed": [
                        {
                            "PolicyKey": "default/anp2",
                            "Priority": 2,
                            "RuleNumber": 1,
                            "Rule": "allow-all-udp",
                            "UDPPorts": "all"
                        }
                    ],
                    "ANPPassed": [
                        {
                            "PolicyKey": "default/anp1",
                            "Priority": 1,
                            "RuleNumber": 1,
                            "Rule": "pass-tcp-80",
                            "TCPPorts": "80"
                        },
                        {
                            "PolicyKey": "default/anp1",
                            "Priority": 1,
                            "RuleNumber": 2,
                            "Rule": "pass-rest-of-tcp",
                            "TCPPorts": "0-79,81-65535"
                        }
                    ],
                    "ANPDenied": [
                        {
                            "PolicyKey": "default/anp3",
                            "Priority": 3,
                            "RuleNumber": 1,
                            "Rule": "deny-everything-else",
                            "OtherPorts": "all"
                        }
                    ],
                    "NPv1Allowed": [
                        {
                            "PolicyKey": "ns-dev/deny-all"
                        },
                        {
                            "PolicyKey": "ns-dev/allow-tcp-80",
                            "TCPPorts": "80"
                        }
                    ]
                },
                "Egress": {
                    "BANPAllowed": [
                        {
                            "PolicyKey": "default/default",
                            "RuleNumber": 1,
                            "Rule": "allow-port-53-and-80",
                            "TCPPorts": "53,80",
                            "UDPPorts": "53,80",
                            "OtherPorts": "53,80",
                        }
                    ],
                    "BANPDenied": [
                        {
                            "PolicyKey": "default/default",
                            "RuleNumber": 2,
                            "Rule": "baseline-deny-udp",
                            "UDPPorts": "0-52,54-65535"
                        }
                    ]
                }
            }
        }
    ]
}

Implementation

  There is a policy engine that calculates whether traffic is allowed/denied for a given set of:

Can we brute force calculate all possible connections between each Deployment/DaemonSet in a cluster? There are only 65,000 ports, so this may be feasible?

Code

It's determined whether traffic is allowed here: https://github.com/kubernetes-sigs/network-policy-api/blob/669dfbc72245a2c7c6f3a3dd5c6188b7af9f8014/cmd/policy-assistant/pkg/matcher/policy.go#L269

https://github.com/kubernetes-sigs/network-policy-api/blob/669dfbc72245a2c7c6f3a3dd5c6188b7af9f8014/cmd/policy-assistant/pkg/matcher/policy.go#L311

Based on the port/protocol logic from the PeerMatcher interface: https://github.com/kubernetes-sigs/network-policy-api/blob/669dfbc72245a2c7c6f3a3dd5c6188b7af9f8014/cmd/policy-assistant/pkg/matcher/peermatcher.go#L29

huntergregory commented 2 months ago

Some good discussion on this today.

Takeaways: