Skip to content

Commit da73b62

Browse files
rejain456sivakami
authored andcommitted
[NPM Lite] Default Deny CNS Changes (#3286)
* updated CNS for adding default deny acl's * added infra nic change * added unit tests * resolved pr comments * updating to fix github checks * added logging lines * removing unnecessary logging lines * removed cni circular dependency * switch from having consts to making them inline * cns changes based on update to network container contrac * fixed spelling * updated unit test * updated test * reverted a comment * updated name of function * changed policy type * added a new line * resolving pr comments * resolving pr comments * re-added back * updated creating acl code to make it more modularized * fixed golint errors * fixed golint * added tests * fixed spelling * moved an assertion line * reformated creating acl's * refactored code per pr comments * fixed lint * moved GetEndpointPolicy so that it is only run on init * updated code * updated error message * updated getEndpointPolicy placement * updated comment * fixed golint issues * refactored * fixed comments * updated return inline * updated unit test returns * corrected the go lint of file
1 parent 0846add commit da73b62

File tree

5 files changed

+397
-116
lines changed

5 files changed

+397
-116
lines changed

cns/middlewares/k8sSwiftV2.go

Lines changed: 86 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -36,124 +36,33 @@ type K8sSWIFTv2Middleware struct {
3636
// Verify interface compliance at compile time
3737
var _ cns.IPConfigsHandlerMiddleware = (*K8sSWIFTv2Middleware)(nil)
3838

39-
// IPConfigsRequestHandlerWrapper is the middleware function for handling SWIFT v2 IP configs requests for AKS-SWIFT. This function wrapped the default SWIFT request
40-
// and release IP configs handlers.
41-
func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, failureHandler cns.IPConfigsHandlerFunc) cns.IPConfigsHandlerFunc {
42-
return func(ctx context.Context, req cns.IPConfigsRequest) (*cns.IPConfigsResponse, error) {
43-
podInfo, respCode, message := k.validateIPConfigsRequest(ctx, &req)
44-
45-
if respCode != types.Success {
46-
return &cns.IPConfigsResponse{
47-
Response: cns.Response{
48-
ReturnCode: respCode,
49-
Message: message,
50-
},
51-
}, errors.New("failed to validate IP configs request")
52-
}
53-
ipConfigsResp, err := defaultHandler(ctx, req)
54-
// If the pod is not v2, return the response from the handler
55-
if !req.SecondaryInterfacesExist {
56-
return ipConfigsResp, err
57-
}
58-
// If the pod is v2, get the infra IP configs from the handler first and then add the SWIFTv2 IP config
59-
defer func() {
60-
// Release the default IP config if there is an error
61-
if err != nil {
62-
_, err = failureHandler(ctx, req)
63-
if err != nil {
64-
logger.Errorf("failed to release default IP config : %v", err)
65-
}
66-
}
67-
}()
68-
if err != nil {
69-
return ipConfigsResp, err
70-
}
71-
SWIFTv2PodIPInfos, err := k.getIPConfig(ctx, podInfo)
72-
if err != nil {
73-
return &cns.IPConfigsResponse{
74-
Response: cns.Response{
75-
ReturnCode: types.FailedToAllocateIPConfig,
76-
Message: fmt.Sprintf("AllocateIPConfig failed: %v, IP config request is %v", err, req),
77-
},
78-
PodIPInfo: []cns.PodIpInfo{},
79-
}, errors.Wrapf(err, "failed to get SWIFTv2 IP config : %v", req)
80-
}
81-
ipConfigsResp.PodIPInfo = append(ipConfigsResp.PodIPInfo, SWIFTv2PodIPInfos...)
82-
// Set routes for the pod
83-
for i := range ipConfigsResp.PodIPInfo {
84-
ipInfo := &ipConfigsResp.PodIPInfo[i]
85-
// Backend nics doesn't need routes to be set
86-
if ipInfo.NICType != cns.BackendNIC {
87-
err = k.setRoutes(ipInfo)
88-
if err != nil {
89-
return &cns.IPConfigsResponse{
90-
Response: cns.Response{
91-
ReturnCode: types.FailedToAllocateIPConfig,
92-
Message: fmt.Sprintf("AllocateIPConfig failed: %v, IP config request is %v", err, req),
93-
},
94-
PodIPInfo: []cns.PodIpInfo{},
95-
}, errors.Wrapf(err, "failed to set routes for pod %s", podInfo.Name())
96-
}
97-
}
98-
}
99-
return ipConfigsResp, nil
39+
func (k *K8sSWIFTv2Middleware) GetPodInfoForIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string) {
40+
// gets pod info for the specified request
41+
podInfo, pod, respCode, message := k.GetPodInfo(ctx, req)
42+
if respCode != types.Success {
43+
return nil, respCode, message
10044
}
101-
}
10245

103-
// validateIPConfigsRequest validates if pod is multitenant by checking the pod labels, used in SWIFT V2 AKS scenario.
104-
// nolint
105-
func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string) {
106-
// Retrieve the pod from the cluster
107-
podInfo, err := cns.UnmarshalPodInfo(req.OrchestratorContext)
108-
if err != nil {
109-
errBuf := errors.Wrapf(err, "failed to unmarshalling pod info from ipconfigs request %+v", req)
110-
return nil, types.UnexpectedError, errBuf.Error()
111-
}
112-
logger.Printf("[SWIFTv2Middleware] validate ipconfigs request for pod %s", podInfo.Name())
113-
podNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
114-
pod := v1.Pod{}
115-
if err := k.Cli.Get(ctx, podNamespacedName, &pod); err != nil {
116-
errBuf := errors.Wrapf(err, "failed to get pod %+v", podNamespacedName)
117-
return nil, types.UnexpectedError, errBuf.Error()
118-
}
119-
120-
// check the pod labels for Swift V2, set the request's SecondaryInterfaceSet flag to true and check if its MTPNC CRD is ready
121-
_, swiftV2PodNetworkLabel := pod.Labels[configuration.LabelPodSwiftV2]
122-
_, swiftV2PodNetworkInstanceLabel := pod.Labels[configuration.LabelPodNetworkInstanceSwiftV2]
123-
if swiftV2PodNetworkLabel || swiftV2PodNetworkInstanceLabel {
46+
// validates if pod is swiftv2
47+
isSwiftv2 := ValidateSwiftv2Pod(pod)
12448

125-
// Check if the MTPNC CRD exists for the pod, if not, return error
126-
mtpnc := v1alpha1.MultitenantPodNetworkConfig{}
127-
mtpncNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
128-
if err := k.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil {
129-
return nil, types.UnexpectedError, fmt.Errorf("failed to get pod's mtpnc from cache : %w", err).Error()
130-
}
131-
// Check if the MTPNC CRD is ready. If one of the fields is empty, return error
132-
if !mtpnc.IsReady() {
133-
return nil, types.UnexpectedError, errMTPNCNotReady.Error()
134-
}
135-
// If primary Ip is set in status field, it indicates the presence of secondary interfaces
136-
if mtpnc.Status.PrimaryIP != "" {
137-
req.SecondaryInterfacesExist = true
49+
var mtpnc v1alpha1.MultitenantPodNetworkConfig
50+
// if swiftv2 is enabled, get mtpnc
51+
if isSwiftv2 {
52+
mtpnc, respCode, message = k.getMTPNC(ctx, podInfo)
53+
if respCode != types.Success {
54+
return nil, respCode, message
13855
}
139-
interfaceInfos := mtpnc.Status.InterfaceInfos
140-
for _, interfaceInfo := range interfaceInfos {
141-
if interfaceInfo.DeviceType == v1alpha1.DeviceTypeInfiniBandNIC {
142-
if interfaceInfo.MacAddress == "" || interfaceInfo.NCID == "" {
143-
return nil, types.UnexpectedError, errMTPNCNotReady.Error()
144-
}
145-
req.BackendInterfaceExist = true
146-
req.BackendInterfaceMacAddresses = append(req.BackendInterfaceMacAddresses, interfaceInfo.MacAddress)
14756

148-
}
149-
if interfaceInfo.DeviceType == v1alpha1.DeviceTypeVnetNIC {
150-
req.SecondaryInterfacesExist = true
151-
}
57+
// update ipConfigRequest
58+
respCode, message = k.UpdateIPConfigRequest(mtpnc, req)
59+
if respCode != types.Success {
60+
return nil, respCode, message
15261
}
15362
}
15463
logger.Printf("[SWIFTv2Middleware] pod %s has secondary interface : %v", podInfo.Name(), req.SecondaryInterfacesExist)
15564
logger.Printf("[SWIFTv2Middleware] pod %s has backend interface : %v", podInfo.Name(), req.BackendInterfaceExist)
156-
// retrieve podinfo from orchestrator context
65+
15766
return podInfo, types.Success, ""
15867
}
15968

@@ -249,3 +158,71 @@ func (k *K8sSWIFTv2Middleware) getIPConfig(ctx context.Context, podInfo cns.PodI
249158
func (k *K8sSWIFTv2Middleware) Type() cns.SWIFTV2Mode {
250159
return cns.K8sSWIFTV2
251160
}
161+
162+
// gets Pod Data
163+
func (k *K8sSWIFTv2Middleware) GetPodInfo(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, k8sPod v1.Pod, respCode types.ResponseCode, message string) {
164+
// Retrieve the pod from the cluster
165+
podInfo, err := cns.UnmarshalPodInfo(req.OrchestratorContext)
166+
if err != nil {
167+
errBuf := errors.Wrapf(err, "failed to unmarshalling pod info from ipconfigs request %+v", req)
168+
return nil, v1.Pod{}, types.UnexpectedError, errBuf.Error()
169+
}
170+
logger.Printf("[SWIFTv2Middleware] validate ipconfigs request for pod %s", podInfo.Name())
171+
podNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
172+
pod := v1.Pod{}
173+
if err := k.Cli.Get(ctx, podNamespacedName, &pod); err != nil {
174+
errBuf := errors.Wrapf(err, "failed to get pod %+v", podNamespacedName)
175+
return nil, v1.Pod{}, types.UnexpectedError, errBuf.Error()
176+
}
177+
return podInfo, pod, types.Success, ""
178+
}
179+
180+
// validates if pod is multitenant by checking the pod labels, used in SWIFT V2 AKS scenario.
181+
func ValidateSwiftv2Pod(pod v1.Pod) bool {
182+
// check the pod labels for Swift V2
183+
_, swiftV2PodNetworkLabel := pod.Labels[configuration.LabelPodSwiftV2]
184+
_, swiftV2PodNetworkInstanceLabel := pod.Labels[configuration.LabelPodNetworkInstanceSwiftV2]
185+
return swiftV2PodNetworkLabel || swiftV2PodNetworkInstanceLabel
186+
}
187+
188+
func (k *K8sSWIFTv2Middleware) getMTPNC(ctx context.Context, podInfo cns.PodInfo) (mtpncResource v1alpha1.MultitenantPodNetworkConfig, respCode types.ResponseCode, message string) {
189+
// Check if the MTPNC CRD exists for the pod, if not, return error
190+
mtpnc := v1alpha1.MultitenantPodNetworkConfig{}
191+
mtpncNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
192+
if err := k.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil {
193+
return v1alpha1.MultitenantPodNetworkConfig{}, types.UnexpectedError, fmt.Errorf("failed to get pod's mtpnc from cache : %w", err).Error()
194+
}
195+
// Check if the MTPNC CRD is ready. If one of the fields is empty, return error
196+
if !mtpnc.IsReady() {
197+
return v1alpha1.MultitenantPodNetworkConfig{}, types.UnexpectedError, errMTPNCNotReady.Error()
198+
}
199+
return mtpnc, types.Success, ""
200+
}
201+
202+
// Updates Ip Config Request
203+
func (k *K8sSWIFTv2Middleware) UpdateIPConfigRequest(mtpnc v1alpha1.MultitenantPodNetworkConfig, req *cns.IPConfigsRequest) (
204+
respCode types.ResponseCode,
205+
message string,
206+
) {
207+
// If primary Ip is set in status field, it indicates the presence of secondary interfaces
208+
if mtpnc.Status.PrimaryIP != "" {
209+
req.SecondaryInterfacesExist = true
210+
}
211+
212+
interfaceInfos := mtpnc.Status.InterfaceInfos
213+
for _, interfaceInfo := range interfaceInfos {
214+
if interfaceInfo.DeviceType == v1alpha1.DeviceTypeInfiniBandNIC {
215+
if interfaceInfo.MacAddress == "" || interfaceInfo.NCID == "" {
216+
return types.UnexpectedError, errMTPNCNotReady.Error()
217+
}
218+
req.BackendInterfaceExist = true
219+
req.BackendInterfaceMacAddresses = append(req.BackendInterfaceMacAddresses, interfaceInfo.MacAddress)
220+
221+
}
222+
if interfaceInfo.DeviceType == v1alpha1.DeviceTypeVnetNIC {
223+
req.SecondaryInterfacesExist = true
224+
}
225+
}
226+
227+
return types.Success, ""
228+
}

cns/middlewares/k8sSwiftV2_linux.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package middlewares
22

33
import (
4+
"context"
45
"fmt"
56
"net/netip"
67

78
"github.com/Azure/azure-container-networking/cns"
89
"github.com/Azure/azure-container-networking/cns/configuration"
910
"github.com/Azure/azure-container-networking/cns/logger"
1011
"github.com/Azure/azure-container-networking/cns/middlewares/utils"
12+
"github.com/Azure/azure-container-networking/cns/types"
1113
"github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1"
1214
"github.com/pkg/errors"
1315
)
@@ -103,3 +105,67 @@ func (k *K8sSWIFTv2Middleware) assignSubnetPrefixLengthFields(_ *cns.PodIpInfo,
103105
}
104106

105107
func (k *K8sSWIFTv2Middleware) addDefaultRoute(*cns.PodIpInfo, string) {}
108+
109+
// IPConfigsRequestHandlerWrapper is the middleware function for handling SWIFT v2 IP configs requests for AKS-SWIFT. This function wrapped the default SWIFT request
110+
// and release IP configs handlers.
111+
func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, failureHandler cns.IPConfigsHandlerFunc) cns.IPConfigsHandlerFunc {
112+
return func(ctx context.Context, req cns.IPConfigsRequest) (*cns.IPConfigsResponse, error) {
113+
podInfo, respCode, message := k.GetPodInfoForIPConfigsRequest(ctx, &req)
114+
115+
if respCode != types.Success {
116+
return &cns.IPConfigsResponse{
117+
Response: cns.Response{
118+
ReturnCode: respCode,
119+
Message: message,
120+
},
121+
}, errors.New("failed to validate IP configs request")
122+
}
123+
ipConfigsResp, err := defaultHandler(ctx, req)
124+
// If the pod is not v2, return the response from the handler
125+
if !req.SecondaryInterfacesExist {
126+
return ipConfigsResp, err
127+
}
128+
// If the pod is v2, get the infra IP configs from the handler first and then add the SWIFTv2 IP config
129+
defer func() {
130+
// Release the default IP config if there is an error
131+
if err != nil {
132+
_, err = failureHandler(ctx, req)
133+
if err != nil {
134+
logger.Errorf("failed to release default IP config : %v", err)
135+
}
136+
}
137+
}()
138+
if err != nil {
139+
return ipConfigsResp, err
140+
}
141+
SWIFTv2PodIPInfos, err := k.getIPConfig(ctx, podInfo)
142+
if err != nil {
143+
return &cns.IPConfigsResponse{
144+
Response: cns.Response{
145+
ReturnCode: types.FailedToAllocateIPConfig,
146+
Message: fmt.Sprintf("AllocateIPConfig failed: %v, IP config request is %v", err, req),
147+
},
148+
PodIPInfo: []cns.PodIpInfo{},
149+
}, errors.Wrapf(err, "failed to get SWIFTv2 IP config : %v", req)
150+
}
151+
ipConfigsResp.PodIPInfo = append(ipConfigsResp.PodIPInfo, SWIFTv2PodIPInfos...)
152+
// Set routes for the pod
153+
for i := range ipConfigsResp.PodIPInfo {
154+
ipInfo := &ipConfigsResp.PodIPInfo[i]
155+
// Backend nics doesn't need routes to be set
156+
if ipInfo.NICType != cns.BackendNIC {
157+
err = k.setRoutes(ipInfo)
158+
if err != nil {
159+
return &cns.IPConfigsResponse{
160+
Response: cns.Response{
161+
ReturnCode: types.FailedToAllocateIPConfig,
162+
Message: fmt.Sprintf("AllocateIPConfig failed: %v, IP config request is %v", err, req),
163+
},
164+
PodIPInfo: []cns.PodIpInfo{},
165+
}, errors.Wrapf(err, "failed to set routes for pod %s", podInfo.Name())
166+
}
167+
}
168+
}
169+
return ipConfigsResp, nil
170+
}
171+
}

cns/middlewares/k8sSwiftV2_linux_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func TestValidateMultitenantIPConfigsRequestSuccess(t *testing.T) {
144144
happyReq.OrchestratorContext = b
145145
happyReq.SecondaryInterfacesExist = false
146146

147-
_, respCode, err := middleware.validateIPConfigsRequest(context.TODO(), happyReq)
147+
_, respCode, err := middleware.GetPodInfoForIPConfigsRequest(context.TODO(), happyReq)
148148
assert.Equal(t, err, "")
149149
assert.Equal(t, respCode, types.Success)
150150
assert.Equal(t, happyReq.SecondaryInterfacesExist, true)
@@ -158,7 +158,7 @@ func TestValidateMultitenantIPConfigsRequestSuccess(t *testing.T) {
158158
happyReq2.OrchestratorContext = b
159159
happyReq2.SecondaryInterfacesExist = false
160160

161-
_, respCode, err = middleware.validateIPConfigsRequest(context.TODO(), happyReq2)
161+
_, respCode, err = middleware.GetPodInfoForIPConfigsRequest(context.TODO(), happyReq2)
162162
assert.Equal(t, err, "")
163163
assert.Equal(t, respCode, types.Success)
164164
assert.Equal(t, happyReq.SecondaryInterfacesExist, true)
@@ -172,7 +172,7 @@ func TestValidateMultitenantIPConfigsRequestSuccess(t *testing.T) {
172172
happyReq3.OrchestratorContext = b
173173
happyReq3.SecondaryInterfacesExist = false
174174

175-
_, respCode, err = middleware.validateIPConfigsRequest(context.TODO(), happyReq3)
175+
_, respCode, err = middleware.GetPodInfoForIPConfigsRequest(context.TODO(), happyReq3)
176176
assert.Equal(t, err, "")
177177
assert.Equal(t, respCode, types.Success)
178178
assert.Equal(t, happyReq3.SecondaryInterfacesExist, false)
@@ -188,7 +188,7 @@ func TestValidateMultitenantIPConfigsRequestFailure(t *testing.T) {
188188
InfraContainerID: testPod1Info.InfraContainerID(),
189189
}
190190
failReq.OrchestratorContext = []byte("invalid")
191-
_, respCode, _ := middleware.validateIPConfigsRequest(context.TODO(), failReq)
191+
_, respCode, _ := middleware.GetPodInfoForIPConfigsRequest(context.TODO(), failReq)
192192
assert.Equal(t, respCode, types.UnexpectedError)
193193

194194
// Pod doesn't exist in cache test
@@ -198,19 +198,19 @@ func TestValidateMultitenantIPConfigsRequestFailure(t *testing.T) {
198198
}
199199
b, _ := testPod2Info.OrchestratorContext()
200200
failReq.OrchestratorContext = b
201-
_, respCode, _ = middleware.validateIPConfigsRequest(context.TODO(), failReq)
201+
_, respCode, _ = middleware.GetPodInfoForIPConfigsRequest(context.TODO(), failReq)
202202
assert.Equal(t, respCode, types.UnexpectedError)
203203

204204
// Failed to get MTPNC
205205
b, _ = testPod3Info.OrchestratorContext()
206206
failReq.OrchestratorContext = b
207-
_, respCode, _ = middleware.validateIPConfigsRequest(context.TODO(), failReq)
207+
_, respCode, _ = middleware.GetPodInfoForIPConfigsRequest(context.TODO(), failReq)
208208
assert.Equal(t, respCode, types.UnexpectedError)
209209

210210
// MTPNC not ready
211211
b, _ = testPod4Info.OrchestratorContext()
212212
failReq.OrchestratorContext = b
213-
_, respCode, _ = middleware.validateIPConfigsRequest(context.TODO(), failReq)
213+
_, respCode, _ = middleware.GetPodInfoForIPConfigsRequest(context.TODO(), failReq)
214214
assert.Equal(t, respCode, types.UnexpectedError)
215215
}
216216

0 commit comments

Comments
 (0)