Skip to content

Commit

Permalink
ingress support in the ingress analyzer (#175)
Browse files Browse the repository at this point in the history
* ingress support in the ingress analyzer
  • Loading branch information
shireenf-ibm committed Jul 26, 2023
1 parent daf7353 commit 9b5ee36
Show file tree
Hide file tree
Showing 80 changed files with 2,325 additions and 548 deletions.
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ issues:
- revive
- goconst
- funlen
- errcheck

run:
timeout: 5m
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ Global Flags:

### List command
```
Lists all allowed connections based on the workloads and network policies defined.
Lists all allowed connections based on the workloads, network policies, and Ingress/Route resources defined.
Connections between workload to itself are excluded from the output.
Usage:
Expand Down Expand Up @@ -102,6 +103,8 @@ default/redis-cart[Deployment] => 0.0.0.0-255.255.255.255 : All Connections
```

Additional details about the connectivity analysis and its output is specified [here](docs/connlist_output.md).

## Build the project

Make sure you have golang 1.19+ on your platform
Expand Down
2 changes: 1 addition & 1 deletion cmd/netpolicy/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func newCommandList() *cobra.Command {
c := &cobra.Command{
Use: "list",
Short: "Lists all allowed connections",
Long: `Lists all allowed connections based on the workloads and network policies
Long: `Lists all allowed connections based on the workloads, network policies, and Ingress/Route resources
defined`,
Example: ` # Get list of allowed connections from resources dir path
k8snetpolicy list --dirpath ./resources_dir/
Expand Down
16 changes: 16 additions & 0 deletions docs/connlist_output.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# List command - connectivity analysis output

Resource manifests considered for a connectivity analysis:
- workload resources (such as Kubernetes Pod / Deployment)
- Kubernetes NetworkPolicy
- Kubernetes Ingress
- Openshift Route

The connectivity output consists of lines of the form: `src` => `dst` : `connections`

For connections inferred from network policy resources only, the `src` and `dst` are workloads or external IP-blocks.

For Ingress/Route analysis, the `src` is specified as `{ingress-controller}`, representing the cluster's ingress controller Pod.
Its connectivity lines are of the form: `{ingress-controller}` => `dst` : `connections`, where `dst` is a workload in the cluster.
This analysis is currently activated only with `--dir-path` flag, and not on a live cluster.
It assumes that the ingress controller Pod is unknown, and thus using this notation of `{ingress-controller}`.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package k8s
package common

import (
"fmt"
Expand Down
26 changes: 26 additions & 0 deletions pkg/netpol/common/connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package common

import (
v1 "k8s.io/api/core/v1"
)

// Connection represents a set of allowed connections between two peers
type Connection interface {
// ProtocolsAndPortsMap returns the set of allowed connections
ProtocolsAndPortsMap() map[v1.Protocol][]PortRange
// AllConnections returns true if all ports are allowed for all protocols
AllConnections() bool
// IsEmpty returns true if no connection is allowed
IsEmpty() bool
}

// PortRange describes a port or a range of ports for allowed traffic
// If start port equals end port, it represents a single port
type PortRange interface {
// Start is the start port
Start() int64
// End is the end port
End() int64
// String returns a string representation of the PortRange object
String() string
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package k8s
package common

import (
"fmt"
Expand All @@ -23,21 +23,22 @@ import (
)

// ConnectionSet represents a set of allowed connections between two peers on a k8s env
// and implements Connection interface
type ConnectionSet struct {
AllowAll bool
AllowedProtocols map[v1.Protocol]*PortSet // map from protocol name to set of allowed ports
}

// MakeConnectionSet returns a ConnectionSet object with all connections or no connections
func MakeConnectionSet(all bool) ConnectionSet {
// MakeConnectionSet returns a pointer to ConnectionSet object with all connections or no connections
func MakeConnectionSet(all bool) *ConnectionSet {
if all {
return ConnectionSet{AllowAll: true, AllowedProtocols: map[v1.Protocol]*PortSet{}}
return &ConnectionSet{AllowAll: true, AllowedProtocols: map[v1.Protocol]*PortSet{}}
}
return ConnectionSet{AllowedProtocols: map[v1.Protocol]*PortSet{}}
return &ConnectionSet{AllowedProtocols: map[v1.Protocol]*PortSet{}}
}

// Intersection updates ConnectionSet object to be the intersection result with other ConnectionSet
func (conn *ConnectionSet) Intersection(other ConnectionSet) {
func (conn *ConnectionSet) Intersection(other *ConnectionSet) {
if other.AllowAll {
return
}
Expand Down Expand Up @@ -92,7 +93,7 @@ func (conn *ConnectionSet) checkIfAllConnections() {
}

// Union updates ConnectionSet object to be the union result with other ConnectionSet
func (conn *ConnectionSet) Union(other ConnectionSet) {
func (conn *ConnectionSet) Union(other *ConnectionSet) {
if conn.AllowAll || other.IsEmpty() {
return
}
Expand Down Expand Up @@ -133,7 +134,7 @@ func (conn *ConnectionSet) Contains(port, protocol string) bool {
}

// ContainedIn returns true if current ConnectionSet is conatained in the input ConnectionSet object
func (conn *ConnectionSet) ContainedIn(other ConnectionSet) bool {
func (conn *ConnectionSet) ContainedIn(other *ConnectionSet) bool {
if other.AllowAll {
return true
}
Expand Down Expand Up @@ -181,7 +182,7 @@ func (conn *ConnectionSet) String() string {
}

// Equal returns true if the current ConnectionSet object is equal to the input object
func (conn *ConnectionSet) Equal(other ConnectionSet) bool {
func (conn *ConnectionSet) Equal(other *ConnectionSet) bool {
if conn.AllowAll != other.AllowAll {
return false
}
Expand All @@ -200,7 +201,7 @@ func (conn *ConnectionSet) Equal(other ConnectionSet) bool {
return true
}

// portRange implements the eval.PortRange interface
// portRange implements the PortRange interface
type portRange struct {
start int64
end int64
Expand All @@ -222,10 +223,10 @@ func (p *portRange) String() string {
}

// ProtocolsAndPortsMap() returns a map from allowed protocol to list of allowed ports ranges.
func (conn *ConnectionSet) ProtocolsAndPortsMap() map[v1.Protocol][]*portRange {
res := map[v1.Protocol][]*portRange{}
func (conn *ConnectionSet) ProtocolsAndPortsMap() map[v1.Protocol][]PortRange {
res := make(map[v1.Protocol][]PortRange, 0)
for protocol, portSet := range conn.AllowedProtocols {
res[protocol] = []*portRange{}
res[protocol] = make([]PortRange, 0)
// TODO: consider leave the slice of ports empty if portSet covers the full range
for i := range portSet.Ports.IntervalSet {
startPort := portSet.Ports.IntervalSet[i].Start
Expand All @@ -236,3 +237,8 @@ func (conn *ConnectionSet) ProtocolsAndPortsMap() map[v1.Protocol][]*portRange {
}
return res
}

// AllConnections returns true if all ports are allowed for all protocols
func (conn *ConnectionSet) AllConnections() bool {
return conn.AllowAll
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package k8s
package common

import (
"testing"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package k8s
package common

import (
"reflect"
Expand Down
Loading

0 comments on commit 9b5ee36

Please sign in to comment.