Skip to content

Commit

Permalink
Add sort-by effectivePriority for antctl get networkpolicy
Browse files Browse the repository at this point in the history
  • Loading branch information
Dyanngg committed Nov 18, 2020
1 parent b1745fc commit 01a0978
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 34 deletions.
9 changes: 9 additions & 0 deletions docs/antctl.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,15 @@ specified local Pod using this `antctl` command:
antctl get networkpolicy -p pod -n namespace
```

Antrea Agent also supports `sort-by=effectivePriority` option, which can be used to
view the effective order in which the NetworkPolicies are evaluated. Antrea-native
NetworkPolicy ordering is documented [here](
antrea-network-policy.md#antrea-native-policy-ordering-based-on-priorities).

```bash
antctl get networkpolicy --sort-by=effectivePriority
```

#### Mapping endpoints to NetworkPolicies

`antctl` supports mapping a specific Pod to the NetworkPolicies which "select"
Expand Down
26 changes: 22 additions & 4 deletions docs/antrea-network-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,10 +480,10 @@ policies will be enforced last.
Within a tier, Antrea-native Policy CRDs are ordered by the `priority` at the policy
level. Thus, the policy with the highest precedence (lowest priority number
value) is enforced first. This ordering is performed solely based on the
`priority` assigned as opposed to the "Kind" of the resource, i.e. the relative
ordering between a [ClusterNetworkPolicy resource](#antrea-clusternetworkpolicy) and an [Antrea NetworkPolicy
resource](#antrea-networkpolicy) within a Tier depends only on the `priority`
set in each of the two resources.
`priority` assigned, as opposed to the "Kind" of the resource, i.e. the relative
ordering between a [ClusterNetworkPolicy resource](#antrea-clusternetworkpolicy) and
an [Antrea NetworkPolicy resource](#antrea-networkpolicy) within a Tier depends only
on the `priority` set in each of the two resources.

### Rule enforcement based on priorities

Expand All @@ -503,6 +503,24 @@ policy rules match, the packet is then enforced for rules created for K8s NP.
If the packet still does not match any rule for K8s NP, it will then be evaluated
against policies created in the "baseline" Tier.

The [antctl command](antctl.md#networkPolicy-commands) with 'sort-by' flag can be used
to check the order of policy enforcemnet on a specific Node. An example output will look like

```text
antctl get netpol --sort-by=effectivePriority
NAME APPLIED-TO RULES SOURCE TIER-PRIORITY PRIORITY
4c504456-9158-4838-bfab-f81665dfae12 85b88ddb-b474-5b44-93d3-c9192c09085e 1 AntreaClusterNetworkPolicy:acnp-1 250 1
41e510e0-e430-4606-b4d9-261424184fba e36f8beb-9b0b-5b49-b1b7-5c5307cddd83 1 AntreaClusterNetworkPolicy:acnp-2 250 2
819b8482-ede5-4423-910c-014b731fdba6 bb6711a1-87c7-5a15-9a4a-71bf49a78056 2 AntreaNetworkPolicy:anp-10 250 10
4d18e031-f05a-48f6-bd91-0197b556ccca e216c104-770c-5731-bfd3-ff4ccbc38c39 2 K8sNetworkPolicy:default/test-1 <NONE> <NONE>
c547002a-d8c7-40f1-bdd1-8eb6d0217a67 e216c104-770c-5731-bfd3-ff4ccbc38c39 1 K8sNetworkPolicy:default/test-2 <NONE> <NONE>
aac8b8bc-f3bf-4c41-b6e0-2af1863204eb bb6711a1-87c7-5a15-9a4a-71bf49a78056 3 AntreaClusterNetworkPolicy:baseline 253 10
```

The [ovs-pipeline doc](design/ovs-pipeline.md) contains more information on how
policy rules are realized by OpenFlow, and how the priority of flows reflects the
order in which they are enforced.

## RBAC

Antrea-native Policy CRDs are meant for admins to manage the security of their
Expand Down
64 changes: 59 additions & 5 deletions pkg/agent/apiserver/handlers/networkpolicy/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,20 @@ import (
"fmt"
"net/http"
"net/url"
"sort"
"strings"

agentquerier "github.com/vmware-tanzu/antrea/pkg/agent/querier"
cpv1beta "github.com/vmware-tanzu/antrea/pkg/apis/controlplane/v1beta2"
"github.com/vmware-tanzu/antrea/pkg/controller/networkpolicy"
"github.com/vmware-tanzu/antrea/pkg/querier"
)

// HandleFunc creates a http.HandlerFunc which uses an AgentNetworkPolicyInfoQuerier
// to query network policy rules in current agent.
func HandleFunc(aq agentquerier.AgentQuerier) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
npFilter, err := newFilterFromURLQuery(r.URL.Query())
npFilter, err := parseURLQuery(r.URL.Query())
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
Expand All @@ -48,15 +50,64 @@ func HandleFunc(aq agentquerier.AgentQuerier) http.HandlerFunc {
} else {
nps = npq.GetNetworkPolicies(npFilter)
}

obj = cpv1beta.NetworkPolicyList{Items: nps}
npSorter := &NPSorter{
networkPolicies: nps,
sortBy: r.URL.Query().Get("sort-by"),
}
sort.Sort(npSorter)
obj = cpv1beta.NetworkPolicyList{Items: npSorter.networkPolicies}

if err := json.NewEncoder(w).Encode(obj); err != nil {
http.Error(w, "Failed to encode response: "+err.Error(), http.StatusInternalServerError)
}
}
}

var (
sortByEffectivePriority = "effectivePriority"
// Compute a tierPriority value in between the application tier and the baseline tier,
// which can be used to sort policies by tier.
effectiveTierPriorityK8sNP = (networkpolicy.DefaultTierPriority + networkpolicy.BaselineTierPriority) / 2
)

type NPSorter struct {
networkPolicies []cpv1beta.NetworkPolicy
sortBy string
}

func (nps *NPSorter) Len() int { return len(nps.networkPolicies) }
func (nps *NPSorter) Swap(i, j int) {
nps.networkPolicies[i], nps.networkPolicies[j] = nps.networkPolicies[j], nps.networkPolicies[i]
}
func (nps *NPSorter) Less(i, j int) bool {
switch nps.sortBy {
case sortByEffectivePriority:
var ti, tj int32
if nps.networkPolicies[i].TierPriority == nil {
ti = effectiveTierPriorityK8sNP
} else {
ti = *nps.networkPolicies[i].TierPriority
}
if nps.networkPolicies[j].TierPriority == nil {
tj = effectiveTierPriorityK8sNP
} else {
tj = *nps.networkPolicies[j].TierPriority
}
pi, pj := nps.networkPolicies[i].Priority, nps.networkPolicies[j].Priority
if ti != tj {
return ti < tj
}
if pi != nil && pj != nil && *pi != *pj {
return *pi < *pj
}
fallthrough
default:
// Do not need a tie-breaker here since NetworkPolicy names are set as UID
// of the source policy and will be unique.
return nps.networkPolicies[i].Name < nps.networkPolicies[j].Name
}
}

// From user shorthand input to cpv1beta1.NetworkPolicyType
var mapToNetworkPolicyType = map[string]cpv1beta.NetworkPolicyType{
"NP": cpv1beta.K8sNetworkPolicy,
Expand All @@ -66,7 +117,7 @@ var mapToNetworkPolicyType = map[string]cpv1beta.NetworkPolicyType{
}

// Create a Network Policy Filter from URL Query
func newFilterFromURLQuery(query url.Values) (*querier.NetworkPolicyQueryFilter, error) {
func parseURLQuery(query url.Values) (*querier.NetworkPolicyQueryFilter, error) {
namespace := query.Get("namespace")
pod := query.Get("pod")
if pod != "" && namespace == "" {
Expand All @@ -80,12 +131,15 @@ func newFilterFromURLQuery(query url.Values) (*querier.NetworkPolicyQueryFilter,
}

source := query.Get("source")

name := query.Get("name")
if name != "" && (source != "" || namespace != "" || pod != "" || strSourceType != "") {
return nil, fmt.Errorf("with a name, none of the other fields can be set")
}

sortBy := query.Get("sort-by")
if sortBy != "" && sortBy != sortByEffectivePriority {
return nil, fmt.Errorf("unsupported sort-by option. Supported value is %s", sortByEffectivePriority)
}
return &querier.NetworkPolicyQueryFilter{
Name: name,
SourceName: source,
Expand Down
7 changes: 7 additions & 0 deletions pkg/antctl/antctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ var CommandList = &commandList{
$ antctl get networkpolicy 6001549b-ba63-4752-8267-30f52b4332db
Get the list of all control plane NetworkPolicies
$ antctl get networkpolicy
Get the list of all control plane NetworkPolicies, sorted by the order in which the policies are evaluated (supported by agent only)
$ antctl get networkpolicy --sort-by=effectivePriority
Get the control plane NetworkPolicy with a specific source (supported by agent only)
$ antctl get networkpolicy -S allow-http -n ns1
Get the list of control plane NetworkPolicies whose source NetworkPolicies are in a Namespace (supported by agent only)
Expand Down Expand Up @@ -153,6 +155,11 @@ var CommandList = &commandList{
usage: "Get NetworkPolicies with specific type. Type means the type of its source network policy: K8sNP, ACNP, ANP",
shorthand: "T",
},
{
name: "sort-by",
usage: "Get NetworkPolicies in specific order. Current supported value is effectivePriority. If not specified, by default results are sorted by name.",
shorthand: "O",
},
},
outputType: multiple,
},
Expand Down
13 changes: 10 additions & 3 deletions pkg/antctl/command_definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ type Foobar struct {
Foo string `json:"foo"`
}

var (
AntreaPolicyTierPriority = int32(250)
AntreaPolicyPriority = float64(1.0)
)

func TestCommandList_tableOutputForGetCommands(t *testing.T) {
for _, tc := range []struct {
name string
Expand Down Expand Up @@ -172,6 +177,8 @@ foo2
ObjectMeta: metav1.ObjectMeta{
Name: "880db7e8-fc2a-4030-aefe-09afc5f341ad",
},
TierPriority: &AntreaPolicyTierPriority,
Priority: &AntreaPolicyPriority,
AppliedToGroups: []string{"32ef631b-6817-5a18-86eb-93f4abf0467c"},
Rules: []cpv1beta.NetworkPolicyRule{
{
Expand All @@ -192,9 +199,9 @@ foo2
},
},
},
expected: `NAME APPLIED-TO RULES SOURCE
6001549b-ba63-4752-8267-30f52b4332db 32ef631b-6817-5a18-86eb-93f4abf0467c + 1 more... 1 K8sNetworkPolicy:default/allow-all
880db7e8-fc2a-4030-aefe-09afc5f341ad 32ef631b-6817-5a18-86eb-93f4abf0467c 2 AntreaNetworkPolicy:default/allow-all
expected: `NAME APPLIED-TO RULES SOURCE TIER-PRIORITY PRIORITY
6001549b-ba63-4752-8267-30f52b4332db 32ef631b-6817-5a18-86eb-93f4abf0467c + 1 more... 1 K8sNetworkPolicy:default/allow-all <NONE> <NONE>
880db7e8-fc2a-4030-aefe-09afc5f341ad 32ef631b-6817-5a18-86eb-93f4abf0467c 2 AntreaNetworkPolicy:default/allow-all 250 1
`,
},
{
Expand Down
21 changes: 18 additions & 3 deletions pkg/antctl/transform/networkpolicy/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,31 @@ func Transform(reader io.Reader, single bool) (interface{}, error) {
)(reader, single)
}

func priorityToString(p interface{}) string {
if reflect.ValueOf(p).IsNil() {
return ""
} else if pInt32, ok := p.(*int32); ok {
return strconv.Itoa(int(*pInt32))
} else {
pFloat64, _ := p.(*float64)
return strconv.FormatFloat(*pFloat64, 'f', -1, 64)
}
}

var _ common.TableOutput = new(Response)

func (r Response) GetTableHeader() []string {
return []string{"NAME", "APPLIED-TO", "RULES", "SOURCE"}
return []string{"NAME", "APPLIED-TO", "RULES", "SOURCE", "TIER-PRIORITY", "PRIORITY"}
}

func (r Response) GetTableRow(maxColumnLength int) []string {
return []string{r.Name, common.GenerateTableElementWithSummary(r.AppliedToGroups, maxColumnLength), strconv.Itoa(len(r.Rules)), r.SourceRef.ToString()}
return []string{
r.Name, common.GenerateTableElementWithSummary(r.AppliedToGroups, maxColumnLength),
strconv.Itoa(len(r.Rules)), r.SourceRef.ToString(),
priorityToString(r.TierPriority), priorityToString(r.Priority),
}
}

func (r Response) SortRows() bool {
return true
return false
}
6 changes: 3 additions & 3 deletions pkg/controller/networkpolicy/antreanetworkpolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) {
UID: "uidA",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down Expand Up @@ -183,7 +183,7 @@ func TestProcessAntreaNetworkPolicy(t *testing.T) {
UID: "uidB",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down Expand Up @@ -286,7 +286,7 @@ func TestAddANP(t *testing.T) {
UID: "uidA",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down
16 changes: 8 additions & 8 deletions pkg/controller/networkpolicy/clusternetworkpolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) {
UID: "uidA",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down Expand Up @@ -185,7 +185,7 @@ func TestProcessClusterNetworkPolicy(t *testing.T) {
UID: "uidB",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down Expand Up @@ -333,7 +333,7 @@ func TestAddCNP(t *testing.T) {
appTier := secv1alpha1.Tier{
ObjectMeta: metav1.ObjectMeta{Name: "application", UID: "tA"},
Spec: secv1alpha1.TierSpec{
Priority: defaultTierPriority,
Priority: DefaultTierPriority,
},
}
allowAction := secv1alpha1.RuleActionAllow
Expand Down Expand Up @@ -390,7 +390,7 @@ func TestAddCNP(t *testing.T) {
UID: "uidA",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down Expand Up @@ -448,7 +448,7 @@ func TestAddCNP(t *testing.T) {
UID: "uidB",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down Expand Up @@ -640,7 +640,7 @@ func TestAddCNP(t *testing.T) {
UID: "uidF",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down Expand Up @@ -724,7 +724,7 @@ func TestAddCNP(t *testing.T) {
UID: "uidG",
},
Priority: &p10,
TierPriority: &defaultTierPriority,
TierPriority: &DefaultTierPriority,
Rules: []controlplane.NetworkPolicyRule{
{
Direction: controlplane.DirectionIn,
Expand Down Expand Up @@ -810,7 +810,7 @@ func TestGetTierPriority(t *testing.T) {
{
name: "empty-tier-name",
inputTier: nil,
expPrio: defaultTierPriority,
expPrio: DefaultTierPriority,
},
{
name: "tier10",
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/networkpolicy/crd_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func (n *NetworkPolicyController) createAddressGroupForCRD(peer secv1alpha1.Netw
// is returned.
func (n *NetworkPolicyController) getTierPriority(tier string) int32 {
if tier == "" {
return defaultTierPriority
return DefaultTierPriority
}
// If the tier name is part of the static tier name set, we need to convert
// tier name to lowercase to match the corresponding Tier CRD name. This is
Expand All @@ -151,7 +151,7 @@ func (n *NetworkPolicyController) getTierPriority(tier string) int32 {
if err != nil {
// This error should ideally not occur as we perform validation.
klog.Errorf("Failed to retrieve Tier %s. Setting default tier priority: %v", tier, err)
return defaultTierPriority
return DefaultTierPriority
}
return t.Spec.Priority
}
Loading

0 comments on commit 01a0978

Please sign in to comment.