Skip to content

Commit

Permalink
[NPM Lite] Support Network Policies Through CNS (#3287)
Browse files Browse the repository at this point in the history
* added npm lite default deny cni changes

* added changes for unit tests

* fixed test message

* moved default deny acl under interfaceinfo

* reverted a change in network

* removed a logging line

* added a new line

* updated unit test

* moved cni kv pair to common folder

* updated cni code to match network container contract update

* updated unit test case

* updated unit test to add cns not sending default deny  acl to cni

* removed an infra nic check

* removed an infra nic check

* removed for loop

* removed an extra spacing

* update from pr comment

* updated unit test

* updated unit tests

* fixed golint
  • Loading branch information
rejain456 authored Feb 1, 2025
1 parent c670d53 commit 0952f5e
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 15 deletions.
5 changes: 5 additions & 0 deletions cni/network/invoker_cns.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/Azure/azure-container-networking/iptables"
"github.com/Azure/azure-container-networking/network"
"github.com/Azure/azure-container-networking/network/networkutils"
"github.com/Azure/azure-container-networking/network/policy"
cniSkel "github.com/containernetworking/cni/pkg/skel"
"github.com/pkg/errors"
"go.uber.org/zap"
Expand Down Expand Up @@ -55,6 +56,7 @@ type IPResultInfo struct {
skipDefaultRoutes bool
routes []cns.Route
pnpID string
endpointPolicies []policy.Policy
}

func (i IPResultInfo) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
Expand Down Expand Up @@ -159,6 +161,7 @@ func (invoker *CNSIPAMInvoker) Add(addConfig IPAMAddConfig) (IPAMAddResult, erro
skipDefaultRoutes: response.PodIPInfo[i].SkipDefaultRoutes,
routes: response.PodIPInfo[i].Routes,
pnpID: response.PodIPInfo[i].PnPID,
endpointPolicies: response.PodIPInfo[i].EndpointPolicies,
}

logger.Info("Received info for pod",
Expand Down Expand Up @@ -444,6 +447,7 @@ func configureDefaultAddResult(info *IPResultInfo, addConfig *IPAMAddConfig, add
Gw: ncgw,
})
}

// if we have multiple infra ip result infos, we effectively append routes and ip configs to that same interface info each time
// the host subnet prefix (in ipv4 or ipv6) will always refer to the same interface regardless of which ip result info we look at
addResult.interfaceInfo[key] = network.InterfaceInfo{
Expand All @@ -452,6 +456,7 @@ func configureDefaultAddResult(info *IPResultInfo, addConfig *IPAMAddConfig, add
IPConfigs: ipConfigs,
Routes: resRoute,
HostSubnetPrefix: *hostIPNet,
EndpointPolicies: info.endpointPolicies,
}
}

Expand Down
81 changes: 66 additions & 15 deletions cni/network/invoker_cns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/Azure/azure-container-networking/cns"
"github.com/Azure/azure-container-networking/iptables"
"github.com/Azure/azure-container-networking/network"
"github.com/Azure/azure-container-networking/network/policy"
cniSkel "github.com/containernetworking/cni/pkg/skel"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -521,14 +522,38 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
hostSubnetPrefix *net.IPNet
options map[string]interface{}
}
valueOut := []byte(`{
"Type": "ACL",
"Action": "Block",
"Direction": "Out",
"Priority": 10000
}`)

valueIn := []byte(`{
"Type": "ACL",
"Action": "Block",
"Direction": "In",
"Priority": 10000
}`)

expectedEndpointPolicies := []policy.Policy{
{
Type: policy.EndpointPolicy,
Data: valueOut,
},
{
Type: policy.EndpointPolicy,
Data: valueIn,
},
}
tests := []struct {
name string
fields fields
args args
wantDefaultResult network.InterfaceInfo
wantMultitenantResult network.InterfaceInfo
wantErr bool
name string
fields fields
args args
wantDefaultDenyEndpoints bool
wantDefaultResult network.InterfaceInfo
wantMultitenantResult network.InterfaceInfo
wantErr bool
}{
{
name: "Test happy CNI add",
Expand Down Expand Up @@ -559,7 +584,8 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
PrimaryIP: "10.0.0.1",
Subnet: "10.0.0.0/24",
},
NICType: cns.InfraNIC,
NICType: cns.InfraNIC,
EndpointPolicies: expectedEndpointPolicies,
},
},
Response: cns.Response{
Expand Down Expand Up @@ -588,6 +614,7 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
Gateway: net.ParseIP("10.0.0.1"),
},
},
EndpointPolicies: expectedEndpointPolicies,
Routes: []network.RouteInfo{
{
Dst: network.Ipv4DefaultRouteDstPrefix,
Expand All @@ -597,7 +624,8 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
NICType: cns.InfraNIC,
HostSubnetPrefix: *parseCIDR("10.0.0.0/24"),
},
wantErr: false,
wantDefaultDenyEndpoints: true,
wantErr: false,
},
{
name: "Test CNI add with pod ip info empty nictype",
Expand Down Expand Up @@ -665,7 +693,8 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
NICType: cns.InfraNIC,
HostSubnetPrefix: *parseCIDR("10.0.0.0/24"),
},
wantErr: false,
wantDefaultDenyEndpoints: false,
wantErr: false,
},
{
name: "Test happy CNI add for both ipv4 and ipv6",
Expand Down Expand Up @@ -696,7 +725,8 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
PrimaryIP: "10.0.0.1",
Subnet: "10.0.0.0/24",
},
NICType: cns.InfraNIC,
NICType: cns.InfraNIC,
EndpointPolicies: expectedEndpointPolicies,
},
{
PodIPConfig: cns.IPSubnet{
Expand All @@ -716,7 +746,8 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
PrimaryIP: "fe80::1234:5678:9abc",
Subnet: "fd11:1234::/112",
},
NICType: cns.InfraNIC,
NICType: cns.InfraNIC,
EndpointPolicies: expectedEndpointPolicies,
},
},
Response: cns.Response{
Expand Down Expand Up @@ -749,6 +780,7 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
Gateway: net.ParseIP("fe80::1234:5678:9abc"),
},
},
EndpointPolicies: expectedEndpointPolicies,
Routes: []network.RouteInfo{
{
Dst: network.Ipv4DefaultRouteDstPrefix,
Expand All @@ -762,7 +794,8 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
NICType: cns.InfraNIC,
HostSubnetPrefix: *parseCIDR("fd11:1234::/112"),
},
wantErr: false,
wantDefaultDenyEndpoints: true,
wantErr: false,
},
{
name: "fail to request IP addresses from cns",
Expand All @@ -773,12 +806,24 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
require: require,
requestIPs: requestIPsHandler{
ipconfigArgument: getTestIPConfigsRequest(),
result: nil,
err: errors.New("failed error from CNS"), //nolint "error for ut"
result: &cns.IPConfigsResponse{
PodIPInfo: []cns.PodIpInfo{
{
EndpointPolicies: expectedEndpointPolicies,
},
},
Response: cns.Response{
ReturnCode: 0,
Message: "",
},
},
err: errors.New("failed error from CNS"), //nolint "error for ut"

},
},
},
wantErr: true,
wantDefaultDenyEndpoints: false,
wantErr: true,
},
}
for _, tt := range tests {
Expand All @@ -794,6 +839,7 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
}
ipamAddResult, err := invoker.Add(IPAMAddConfig{nwCfg: tt.args.nwCfg, args: tt.args.args, options: tt.args.options})
if tt.wantErr {
require.Equalf([]policy.Policy(nil), ipamAddResult.interfaceInfo[string(cns.InfraNIC)].EndpointPolicies, "There was an error requesting IP addresses from cns")
require.Error(err)
} else {
require.NoError(err)
Expand All @@ -809,6 +855,11 @@ func TestCNSIPAMInvoker_Add(t *testing.T) {
}
if ifInfo.NICType == cns.InfraNIC {
require.Equalf(tt.wantDefaultResult, ifInfo, "incorrect default response")
if tt.wantDefaultDenyEndpoints {
require.Equalf(expectedEndpointPolicies, ifInfo.EndpointPolicies, "Correct default deny ACL")
} else {
require.Equalf([]policy.Policy(nil), ifInfo.EndpointPolicies, "Correct default deny ACL")
}
}
}
})
Expand Down
4 changes: 4 additions & 0 deletions cni/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,10 @@ func (plugin *NetPlugin) createEpInfo(opt *createEpInfoOpt) (*network.EndpointIn
// create endpoint policies by appending to network policies
// the value passed into NetworkPolicies should be unaffected since we reassign here
opt.policies = append(opt.policies, endpointPolicies...)

// appends endpoint policies specific to this interface
opt.policies = append(opt.policies, opt.ifInfo.EndpointPolicies...)

endpointInfo.EndpointPolicies = opt.policies
// add even more endpoint policies
epPolicies, err := getPoliciesFromRuntimeCfg(opt.nwCfg, opt.ipamAddResult.ipv6Enabled) // not specific to delegated or infra
Expand Down
26 changes: 26 additions & 0 deletions cni/network/network_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,12 @@ func GetTestCNSResponseSecondaryWindows(macAddress string) map[string]network.In
SkipDefaultRoutes: true,
NICType: cns.InfraNIC,
HostSubnetPrefix: *getCIDRNotationForAddress("20.224.0.0/16"),
EndpointPolicies: []policy.Policy{
{
Type: policy.EndpointPolicy,
Data: GetRawACLPolicy(),
},
},
},
macAddress: {
MacAddress: parsedMAC,
Expand All @@ -895,6 +901,12 @@ func GetTestCNSResponseSecondaryWindows(macAddress string) map[string]network.In
},
},
NICType: cns.NodeNetworkInterfaceFrontendNIC,
EndpointPolicies: []policy.Policy{
{
Type: policy.EndpointPolicy,
Data: GetRawOutBoundNATPolicy(),
},
},
},
}
}
Expand Down Expand Up @@ -1226,6 +1238,12 @@ func TestPluginWindowsAdd(t *testing.T) {
Gateway: net.ParseIP("10.244.2.1"),
},
},
EndpointPolicies: []policy.Policy{
{
Type: policy.EndpointPolicy,
Data: GetRawACLPolicy(),
},
},
},
epIDRegex: `.*`,
},
Expand Down Expand Up @@ -1269,6 +1287,12 @@ func TestPluginWindowsAdd(t *testing.T) {
Gateway: net.ParseIP("10.241.0.1"),
},
},
EndpointPolicies: []policy.Policy{
{
Type: policy.EndpointPolicy,
Data: GetRawOutBoundNATPolicy(),
},
},
},
epIDRegex: `.*`,
},
Expand Down Expand Up @@ -1326,6 +1350,8 @@ func TestPluginWindowsAdd(t *testing.T) {
epInfo1.EndpointPolicies[0] = policy.Policy{
Type: policy.ACLPolicy,
}
require.Len(t, epInfo1.EndpointPolicies, 1)
require.Len(t, epInfo2.EndpointPolicies, 1)
require.NotEqual(t, epInfo1.EndpointPolicies, epInfo2.EndpointPolicies)
}
// ensure the network policy slices are separate entities when in separate endpoint infos
Expand Down
1 change: 1 addition & 0 deletions network/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ type InterfaceInfo struct {
HostSubnetPrefix net.IPNet // Move this field from ipamAddResult
NCResponse *cns.GetNetworkContainerResponse
PnPID string
EndpointPolicies []policy.Policy
}

type IPConfig struct {
Expand Down

0 comments on commit 0952f5e

Please sign in to comment.