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

[NPM Lite] Support Network Policies Through CNS #3287

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 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
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"
paulyufan2 marked this conversation as resolved.
Show resolved Hide resolved

},
},
},
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 @@
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 @@
},
},
NICType: cns.NodeNetworkInterfaceFrontendNIC,
EndpointPolicies: []policy.Policy{
{
Type: policy.EndpointPolicy,
Data: GetRawOutBoundNATPolicy(),
},
},
},
}
}
Expand Down Expand Up @@ -1226,6 +1238,12 @@
Gateway: net.ParseIP("10.244.2.1"),
},
},
EndpointPolicies: []policy.Policy{
{
Type: policy.EndpointPolicy,
Data: GetRawACLPolicy(),
},
},
},
epIDRegex: `.*`,
},
Expand Down Expand Up @@ -1269,6 +1287,12 @@
Gateway: net.ParseIP("10.241.0.1"),
},
},
EndpointPolicies: []policy.Policy{
{
Type: policy.EndpointPolicy,
Data: GetRawOutBoundNATPolicy(),
},
},
},
epIDRegex: `.*`,
},
Expand Down Expand Up @@ -1326,6 +1350,8 @@
epInfo1.EndpointPolicies[0] = policy.Policy{
Type: policy.ACLPolicy,
}
require.Equal(t, len(epInfo1.EndpointPolicies), 1)

Check failure on line 1353 in cni/network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

len: use require.Len (testifylint)

Check failure on line 1353 in cni/network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

len: use require.Len (testifylint)
require.Equal(t, len(epInfo2.EndpointPolicies), 1)

Check failure on line 1354 in cni/network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

len: use require.Len (testifylint)

Check failure on line 1354 in cni/network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

len: use require.Len (testifylint)
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
Loading