Skip to content

Commit d951865

Browse files
committed
updated CNS for adding default deny acl's
1 parent 7e6e30d commit d951865

File tree

7 files changed

+112
-15
lines changed

7 files changed

+112
-15
lines changed

cns/NetworkContainerContract.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strconv"
88
"strings"
99

10+
"github.com/Azure/azure-container-networking/cni"
1011
"github.com/Azure/azure-container-networking/cns/types"
1112
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
1213
"github.com/google/uuid"
@@ -503,6 +504,8 @@ type PodIpInfo struct {
503504
Routes []Route
504505
// PnpId is set for backend interfaces, Pnp Id identifies VF. Plug and play id(pnp) is also called as PCI ID
505506
PnPID string
507+
// Defauly Deny ACL's to configure on HNS endpoints for Swiftv2 window nodes
508+
DefaultDenyACL []cni.KVPair
506509
}
507510

508511
type HostIPInfo struct {

cns/middlewares/k8sSwiftV2.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ var _ cns.IPConfigsHandlerMiddleware = (*K8sSWIFTv2Middleware)(nil)
4040
// and release IP configs handlers.
4141
func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, failureHandler cns.IPConfigsHandlerFunc) cns.IPConfigsHandlerFunc {
4242
return func(ctx context.Context, req cns.IPConfigsRequest) (*cns.IPConfigsResponse, error) {
43-
podInfo, respCode, message := k.validateIPConfigsRequest(ctx, &req)
43+
podInfo, respCode, message, defaultDenyACLbool := k.validateIPConfigsRequest(ctx, &req)
44+
45+
logger.Printf("defaultDenyACLbool value is: %v", defaultDenyACLbool)
4446

4547
if respCode != types.Success {
4648
return &cns.IPConfigsResponse{
@@ -55,6 +57,19 @@ func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa
5557
if !req.SecondaryInterfacesExist {
5658
return ipConfigsResp, err
5759
}
60+
61+
// ipConfigsResp has infra IP configs -> if defaultDenyACLbool is enabled, add the default deny acl's pn the infra IP configs
62+
for i := range ipConfigsResp.PodIPInfo {
63+
ipInfo := &ipConfigsResp.PodIPInfo[i]
64+
// there will be no pod connectivity to and from those pods
65+
if defaultDenyACLbool {
66+
err = addDefaultDenyACL(ipInfo)
67+
if err != nil {
68+
logger.Errorf("failed to add default deny acl's for pod %v with err %v", podInfo.Name(), err)
69+
}
70+
}
71+
}
72+
5873
// If the pod is v2, get the infra IP configs from the handler first and then add the SWIFTv2 IP config
5974
defer func() {
6075
// Release the default IP config if there is an error
@@ -102,19 +117,21 @@ func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa
102117

103118
// validateIPConfigsRequest validates if pod is multitenant by checking the pod labels, used in SWIFT V2 AKS scenario.
104119
// nolint
105-
func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string) {
120+
func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string, defaultDenyACL bool) {
121+
defaultDenyACLbool := false
122+
106123
// Retrieve the pod from the cluster
107124
podInfo, err := cns.UnmarshalPodInfo(req.OrchestratorContext)
108125
if err != nil {
109126
errBuf := errors.Wrapf(err, "failed to unmarshalling pod info from ipconfigs request %+v", req)
110-
return nil, types.UnexpectedError, errBuf.Error()
127+
return nil, types.UnexpectedError, errBuf.Error(), defaultDenyACLbool
111128
}
112129
logger.Printf("[SWIFTv2Middleware] validate ipconfigs request for pod %s", podInfo.Name())
113130
podNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
114131
pod := v1.Pod{}
115132
if err := k.Cli.Get(ctx, podNamespacedName, &pod); err != nil {
116133
errBuf := errors.Wrapf(err, "failed to get pod %+v", podNamespacedName)
117-
return nil, types.UnexpectedError, errBuf.Error()
134+
return nil, types.UnexpectedError, errBuf.Error(), defaultDenyACLbool
118135
}
119136

120137
// check the pod labels for Swift V2, set the request's SecondaryInterfaceSet flag to true and check if its MTPNC CRD is ready
@@ -126,12 +143,16 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
126143
mtpnc := v1alpha1.MultitenantPodNetworkConfig{}
127144
mtpncNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
128145
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()
146+
return nil, types.UnexpectedError, fmt.Errorf("failed to get pod's mtpnc from cache : %w", err).Error(), defaultDenyACLbool
130147
}
131148
// Check if the MTPNC CRD is ready. If one of the fields is empty, return error
132149
if !mtpnc.IsReady() {
133-
return nil, types.UnexpectedError, errMTPNCNotReady.Error()
150+
return nil, types.UnexpectedError, errMTPNCNotReady.Error(), defaultDenyACLbool
134151
}
152+
153+
// copying defaultDenyACL bool from mtpnc
154+
defaultDenyACLbool = mtpnc.Status.DefaultDenyACL
155+
135156
// If primary Ip is set in status field, it indicates the presence of secondary interfaces
136157
if mtpnc.Status.PrimaryIP != "" {
137158
req.SecondaryInterfacesExist = true
@@ -140,7 +161,7 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
140161
for _, interfaceInfo := range interfaceInfos {
141162
if interfaceInfo.DeviceType == v1alpha1.DeviceTypeInfiniBandNIC {
142163
if interfaceInfo.MacAddress == "" || interfaceInfo.NCID == "" {
143-
return nil, types.UnexpectedError, errMTPNCNotReady.Error()
164+
return nil, types.UnexpectedError, errMTPNCNotReady.Error(), defaultDenyACLbool
144165
}
145166
req.BackendInterfaceExist = true
146167
req.BackendInterfaceMacAddresses = append(req.BackendInterfaceMacAddresses, interfaceInfo.MacAddress)
@@ -154,7 +175,7 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
154175
logger.Printf("[SWIFTv2Middleware] pod %s has secondary interface : %v", podInfo.Name(), req.SecondaryInterfacesExist)
155176
logger.Printf("[SWIFTv2Middleware] pod %s has backend interface : %v", podInfo.Name(), req.BackendInterfaceExist)
156177
// retrieve podinfo from orchestrator context
157-
return podInfo, types.Success, ""
178+
return podInfo, types.Success, "", defaultDenyACLbool
158179
}
159180

160181
// getIPConfig returns the pod's SWIFT V2 IP configuration.

cns/middlewares/k8sSwiftV2_linux.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,7 @@ func (k *K8sSWIFTv2Middleware) assignSubnetPrefixLengthFields(_ *cns.PodIpInfo,
103103
}
104104

105105
func (k *K8sSWIFTv2Middleware) addDefaultRoute(*cns.PodIpInfo, string) {}
106+
107+
func addDefaultDenyACL(_ *cns.PodIpInfo) error {
108+
return nil
109+
}

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.validateIPConfigsRequest(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.validateIPConfigsRequest(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.validateIPConfigsRequest(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.validateIPConfigsRequest(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.validateIPConfigsRequest(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.validateIPConfigsRequest(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.validateIPConfigsRequest(context.TODO(), failReq)
214214
assert.Equal(t, respCode, types.UnexpectedError)
215215
}
216216

cns/middlewares/k8sSwiftV2_windows.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package middlewares
22

33
import (
4+
"encoding/json"
5+
6+
"github.com/Azure/azure-container-networking/cni"
47
"github.com/Azure/azure-container-networking/cns"
8+
"github.com/Azure/azure-container-networking/cns/logger"
59
"github.com/Azure/azure-container-networking/cns/middlewares/utils"
610
"github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1"
11+
"github.com/Microsoft/hcsshim/hcn"
712
"github.com/pkg/errors"
813
)
914

@@ -58,3 +63,62 @@ func (k *K8sSWIFTv2Middleware) addDefaultRoute(podIPInfo *cns.PodIpInfo, gwIP st
5863
}
5964
podIPInfo.Routes = append(podIPInfo.Routes, route)
6065
}
66+
67+
// append the default deny acl's to the list defaultDenyACL field in podIpInfo
68+
func addDefaultDenyACL(podIpInfo *cns.PodIpInfo) error {
69+
blockEgressACL, err := getDefaultDenyACLPolicy(hcn.DirectionTypeOut)
70+
if err != nil {
71+
return errors.Wrap(err, "Failed to create default deny ACL policy egress")
72+
}
73+
74+
blockIngressACL, err := getDefaultDenyACLPolicy(hcn.DirectionTypeIn)
75+
if err != nil {
76+
return errors.Wrap(err, "Failed to create default deny ACL policy ingress")
77+
}
78+
79+
additionalArgs := []cni.KVPair{
80+
{
81+
Name: "EndpointPolicy",
82+
Value: blockEgressACL,
83+
},
84+
{
85+
Name: "EndpointPolicy",
86+
Value: blockIngressACL,
87+
},
88+
}
89+
90+
podIpInfo.DefaultDenyACL = append(podIpInfo.DefaultDenyACL, additionalArgs...)
91+
92+
logger.Printf("The length of podIpInfo.DefaultDenyACL is: %v", len(podIpInfo.DefaultDenyACL))
93+
94+
return nil
95+
}
96+
97+
// create the default deny acl's that need to be added to the list defaultDenyACL field in podIpInfo
98+
func getDefaultDenyACLPolicy(direction hcn.DirectionType) ([]byte, error) {
99+
const DefaultDenyPriority = 10000
100+
const policyType = "ACL"
101+
type DefaultDenyACL struct {
102+
Type string `json:"Type"`
103+
Action hcn.ActionType `json:"Action"`
104+
Direction hcn.DirectionType `json:"Direction"`
105+
Priority int `json:"Priority"`
106+
}
107+
108+
denyACL := DefaultDenyACL{
109+
Type: policyType,
110+
Action: hcn.ActionTypeBlock,
111+
Direction: direction,
112+
Priority: DefaultDenyPriority,
113+
}
114+
115+
denyACLJSON, err := json.Marshal(denyACL)
116+
117+
logger.Printf("ACL Created for direction %s is : %s", direction, denyACLJSON)
118+
119+
if err != nil {
120+
return nil, errors.Wrap(err, "error marshalling default deny policy to json")
121+
}
122+
123+
return denyACLJSON, nil
124+
}

crd/multitenancy/api/v1alpha1/multitenantpodnetworkconfig.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ type MultitenantPodNetworkConfigStatus struct {
8585
// InterfaceInfos describes all of the network container goal state for this Pod
8686
// +kubebuilder:validation:Optional
8787
InterfaceInfos []InterfaceInfo `json:"interfaceInfos,omitempty"`
88+
// DefaultDenyAcl bool indicates whether default deny policy will be present on the pods upon pod creation
89+
DefaultDenyACL bool `json:"defaultDenyACL"`
8890
}
8991

9092
func init() {

crd/multitenancy/api/v1alpha1/podnetworkinstance.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ type PodNetworkInstanceSpec struct {
5656
// optional for now in case orchestrator uses the deprecated fields
5757
// +kubebuilder:validation:Optional
5858
PodNetworkConfigs []PodNetworkConfig `json:"podNetworkConfigs"`
59+
// DefaultDenyAcl bool indicates whether default deny policy will be present on the pods upon pod creation
60+
// +kubebuilder:default=false
61+
DefaultDenyACL bool `json:"defaultDenyACL"`
5962
}
6063

6164
// PodNetworkInstanceStatus defines the observed state of PodNetworkInstance

0 commit comments

Comments
 (0)