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] Default Deny Policy #3220

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion cni/network/invoker.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ type IPAMAddConfig struct {
type IPAMAddResult struct {
interfaceInfo map[string]network.InterfaceInfo
// ncResponse and host subnet prefix were moved into interface info
ipv6Enabled bool
ipv6Enabled bool
defaultDenyACL []cni.KVPair
}

func (ipamAddResult IPAMAddResult) PrettyString() string {
Expand Down
4 changes: 3 additions & 1 deletion cni/network/invoker_cns.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type IPResultInfo struct {
skipDefaultRoutes bool
routes []cns.Route
pnpID string
defaultDenyACL []cni.KVPair
}

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

logger.Info("Received info for pod",
zap.Any("ipInfo", info),
zap.Any("podInfo", podInfo))
Expand Down Expand Up @@ -444,6 +445,7 @@ func configureDefaultAddResult(info *IPResultInfo, addConfig *IPAMAddConfig, add
Gw: ncgw,
})
}
addResult.defaultDenyACL = append(addResult.defaultDenyACL, info.defaultDenyACL...)
// 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 Down
6 changes: 6 additions & 0 deletions cni/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,14 @@ func (plugin *NetPlugin) Add(args *cniSkel.CmdArgs) error {
// TODO: This proably needs to be changed as we return all interfaces...
// sendEvent(plugin, fmt.Sprintf("Allocated IPAddress from ipam DefaultInterface: %+v, SecondaryInterfaces: %+v", ipamAddResult.interfaceInfo[ifIndex], ipamAddResult.interfaceInfo))
}
var swiftv2DefaultDenyACL []cni.KVPair = []cni.KVPair{}
if len(ipamAddResult.defaultDenyACL) > 0 {
swiftv2DefaultDenyACL = append(swiftv2DefaultDenyACL, ipamAddResult.defaultDenyACL...)
}

nwCfg.AdditionalArgs = append(nwCfg.AdditionalArgs, swiftv2DefaultDenyACL...)
policies := cni.GetPoliciesFromNwCfg(nwCfg.AdditionalArgs)

// moved to addIpamInvoker
// sendEvent(plugin, fmt.Sprintf("Allocated IPAddress from ipam interface: %+v", ipamAddResult.PrettyString()))

Expand Down
3 changes: 3 additions & 0 deletions cns/NetworkContainerContract.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strconv"
"strings"

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

type HostIPInfo struct {
Expand Down
22 changes: 14 additions & 8 deletions cns/middlewares/k8sSwiftV2.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
// and release IP configs handlers.
func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, failureHandler cns.IPConfigsHandlerFunc) cns.IPConfigsHandlerFunc {
return func(ctx context.Context, req cns.IPConfigsRequest) (*cns.IPConfigsResponse, error) {
podInfo, respCode, message := k.validateIPConfigsRequest(ctx, &req)
podInfo, respCode, message, defaultDenyACLbool := k.validateIPConfigsRequest(ctx, &req)

if respCode != types.Success {
return &cns.IPConfigsResponse{
Expand Down Expand Up @@ -84,6 +84,9 @@
ipInfo := &ipConfigsResp.PodIPInfo[i]
// Backend nics doesn't need routes to be set
if ipInfo.NICType != cns.BackendNIC {
if defaultDenyACLbool {
k.addDefaultDenyAcl(ipInfo)

Check failure on line 88 in cns/middlewares/k8sSwiftV2.go

View workflow job for this annotation

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

Error return value of `k.addDefaultDenyAcl` is not checked (errcheck)

Check failure on line 88 in cns/middlewares/k8sSwiftV2.go

View workflow job for this annotation

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

Error return value of `k.addDefaultDenyAcl` is not checked (errcheck)

Check failure on line 88 in cns/middlewares/k8sSwiftV2.go

View workflow job for this annotation

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

Error return value of `k.addDefaultDenyAcl` is not checked (errcheck)

Check failure on line 88 in cns/middlewares/k8sSwiftV2.go

View workflow job for this annotation

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

Error return value of `k.addDefaultDenyAcl` is not checked (errcheck)
}
err = k.setRoutes(ipInfo)
if err != nil {
return &cns.IPConfigsResponse{
Expand All @@ -102,36 +105,39 @@

// validateIPConfigsRequest validates if pod is multitenant by checking the pod labels, used in SWIFT V2 AKS scenario.
// nolint
func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string) {
func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req *cns.IPConfigsRequest) (podInfo cns.PodInfo, respCode types.ResponseCode, message string, defaultDenyACL bool) {
defaultDenyACLbool := false
// Retrieve the pod from the cluster
podInfo, err := cns.UnmarshalPodInfo(req.OrchestratorContext)
if err != nil {
errBuf := errors.Wrapf(err, "failed to unmarshalling pod info from ipconfigs request %+v", req)
return nil, types.UnexpectedError, errBuf.Error()
return nil, types.UnexpectedError, errBuf.Error(), defaultDenyACLbool
}
logger.Printf("[SWIFTv2Middleware] validate ipconfigs request for pod %s", podInfo.Name())
podNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
pod := v1.Pod{}
if err := k.Cli.Get(ctx, podNamespacedName, &pod); err != nil {
errBuf := errors.Wrapf(err, "failed to get pod %+v", podNamespacedName)
return nil, types.UnexpectedError, errBuf.Error()
return nil, types.UnexpectedError, errBuf.Error(), defaultDenyACLbool
}

// check the pod labels for Swift V2, set the request's SecondaryInterfaceSet flag to true and check if its MTPNC CRD is ready
_, swiftV2PodNetworkLabel := pod.Labels[configuration.LabelPodSwiftV2]
_, swiftV2PodNetworkInstanceLabel := pod.Labels[configuration.LabelPodNetworkInstanceSwiftV2]

if swiftV2PodNetworkLabel || swiftV2PodNetworkInstanceLabel {

// Check if the MTPNC CRD exists for the pod, if not, return error
mtpnc := v1alpha1.MultitenantPodNetworkConfig{}
mtpncNamespacedName := k8stypes.NamespacedName{Namespace: podInfo.Namespace(), Name: podInfo.Name()}
if err := k.Cli.Get(ctx, mtpncNamespacedName, &mtpnc); err != nil {
return nil, types.UnexpectedError, fmt.Errorf("failed to get pod's mtpnc from cache : %w", err).Error()
return nil, types.UnexpectedError, fmt.Errorf("failed to get pod's mtpnc from cache : %w", err).Error(), defaultDenyACLbool
}
// Check if the MTPNC CRD is ready. If one of the fields is empty, return error
if !mtpnc.IsReady() {
return nil, types.UnexpectedError, errMTPNCNotReady.Error()
return nil, types.UnexpectedError, errMTPNCNotReady.Error(), defaultDenyACLbool
}
defaultDenyACLbool = mtpnc.Spec.DefaultDenyACL
// If primary Ip is set in status field, it indicates the presence of secondary interfaces
if mtpnc.Status.PrimaryIP != "" {
req.SecondaryInterfacesExist = true
Expand All @@ -140,7 +146,7 @@
for _, interfaceInfo := range interfaceInfos {
if interfaceInfo.DeviceType == v1alpha1.DeviceTypeInfiniBandNIC {
if interfaceInfo.MacAddress == "" || interfaceInfo.NCID == "" {
return nil, types.UnexpectedError, errMTPNCNotReady.Error()
return nil, types.UnexpectedError, errMTPNCNotReady.Error(), defaultDenyACLbool
}
req.BackendInterfaceExist = true
req.BackendInterfaceMacAddresses = append(req.BackendInterfaceMacAddresses, interfaceInfo.MacAddress)
Expand All @@ -154,7 +160,7 @@
logger.Printf("[SWIFTv2Middleware] pod %s has secondary interface : %v", podInfo.Name(), req.SecondaryInterfacesExist)
logger.Printf("[SWIFTv2Middleware] pod %s has backend interface : %v", podInfo.Name(), req.BackendInterfaceExist)
// retrieve podinfo from orchestrator context
return podInfo, types.Success, ""
return podInfo, types.Success, "", defaultDenyACLbool
}

// getIPConfig returns the pod's SWIFT V2 IP configuration.
Expand Down
4 changes: 4 additions & 0 deletions cns/middlewares/k8sSwiftV2_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,7 @@
}

func (k *K8sSWIFTv2Middleware) addDefaultRoute(*cns.PodIpInfo, string) {}

func (k *K8sSWIFTv2Middleware) addDefaultDenyAcl(podIPInfo *cns.PodIpInfo) error {

Check failure on line 107 in cns/middlewares/k8sSwiftV2_linux.go

View workflow job for this annotation

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

var-naming: method addDefaultDenyAcl should be addDefaultDenyACL (revive)

Check failure on line 107 in cns/middlewares/k8sSwiftV2_linux.go

View workflow job for this annotation

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

unused-parameter: parameter 'podIPInfo' seems to be unused, consider removing or renaming it as _ (revive)
return nil
}
14 changes: 7 additions & 7 deletions cns/middlewares/k8sSwiftV2_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func TestValidateMultitenantIPConfigsRequestSuccess(t *testing.T) {
happyReq.OrchestratorContext = b
happyReq.SecondaryInterfacesExist = false

_, respCode, err := middleware.validateIPConfigsRequest(context.TODO(), happyReq)
_, respCode, err, _ := middleware.validateIPConfigsRequest(context.TODO(), happyReq)
assert.Equal(t, err, "")
assert.Equal(t, respCode, types.Success)
assert.Equal(t, happyReq.SecondaryInterfacesExist, true)
Expand All @@ -158,7 +158,7 @@ func TestValidateMultitenantIPConfigsRequestSuccess(t *testing.T) {
happyReq2.OrchestratorContext = b
happyReq2.SecondaryInterfacesExist = false

_, respCode, err = middleware.validateIPConfigsRequest(context.TODO(), happyReq2)
_, respCode, err, _ = middleware.validateIPConfigsRequest(context.TODO(), happyReq2)
assert.Equal(t, err, "")
assert.Equal(t, respCode, types.Success)
assert.Equal(t, happyReq.SecondaryInterfacesExist, true)
Expand All @@ -172,7 +172,7 @@ func TestValidateMultitenantIPConfigsRequestSuccess(t *testing.T) {
happyReq3.OrchestratorContext = b
happyReq3.SecondaryInterfacesExist = false

_, respCode, err = middleware.validateIPConfigsRequest(context.TODO(), happyReq3)
_, respCode, err, _ = middleware.validateIPConfigsRequest(context.TODO(), happyReq3)
assert.Equal(t, err, "")
assert.Equal(t, respCode, types.Success)
assert.Equal(t, happyReq3.SecondaryInterfacesExist, false)
Expand All @@ -188,7 +188,7 @@ func TestValidateMultitenantIPConfigsRequestFailure(t *testing.T) {
InfraContainerID: testPod1Info.InfraContainerID(),
}
failReq.OrchestratorContext = []byte("invalid")
_, respCode, _ := middleware.validateIPConfigsRequest(context.TODO(), failReq)
_, respCode, _, _ := middleware.validateIPConfigsRequest(context.TODO(), failReq)
assert.Equal(t, respCode, types.UnexpectedError)

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

// Failed to get MTPNC
b, _ = testPod3Info.OrchestratorContext()
failReq.OrchestratorContext = b
_, respCode, _ = middleware.validateIPConfigsRequest(context.TODO(), failReq)
_, respCode, _, _ = middleware.validateIPConfigsRequest(context.TODO(), failReq)
assert.Equal(t, respCode, types.UnexpectedError)

// MTPNC not ready
b, _ = testPod4Info.OrchestratorContext()
failReq.OrchestratorContext = b
_, respCode, _ = middleware.validateIPConfigsRequest(context.TODO(), failReq)
_, respCode, _, _ = middleware.validateIPConfigsRequest(context.TODO(), failReq)
assert.Equal(t, respCode, types.UnexpectedError)
}

Expand Down
35 changes: 35 additions & 0 deletions cns/middlewares/k8sSwiftV2_windows.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package middlewares

import (
"encoding/json"
"fmt"

"github.com/Azure/azure-container-networking/cni"
"github.com/Azure/azure-container-networking/cns"
"github.com/Azure/azure-container-networking/cns/middlewares/utils"
"github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1"
"github.com/Microsoft/hcsshim/hcn"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -58,3 +63,33 @@
}
podIPInfo.Routes = append(podIPInfo.Routes, route)
}

func (k *K8sSWIFTv2Middleware) addDefaultDenyAcl(podIPInfo *cns.PodIpInfo) error {

Check failure on line 67 in cns/middlewares/k8sSwiftV2_windows.go

View workflow job for this annotation

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

var-naming: method addDefaultDenyAcl should be addDefaultDenyACL (revive)

Check failure on line 67 in cns/middlewares/k8sSwiftV2_windows.go

View workflow job for this annotation

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

var-naming: method addDefaultDenyAcl should be addDefaultDenyACL (revive)
additionalArgs := []cni.KVPair{
{
Name: "EndpointPolicy",
Value: getDefaultDenyACLPolicy(hcn.DirectionTypeOut),
},
{
Name: "EndpointPolicy",
Value: getDefaultDenyACLPolicy(hcn.DirectionTypeIn),
},
}
podIPInfo.DefaultDenyACL = append(podIPInfo.DefaultDenyACL, additionalArgs...) //insert acl here

Check failure on line 78 in cns/middlewares/k8sSwiftV2_windows.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)

Check failure on line 78 in cns/middlewares/k8sSwiftV2_windows.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)
return nil
}

func getDefaultDenyACLPolicy(direction hcn.DirectionType) []byte {
denyACL := map[string]interface{}{
"Type": "ACL",
"Action": hcn.ActionTypeBlock,
"Direction": direction,
"Priority": "1000",
}
denyACLJSON, err := json.Marshal(denyACL)
if err != nil {
fmt.Println("Error marshaling default deny policy:", err)
return nil
}
return denyACLJSON
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
PodNetwork string `json:"podNetwork"`
// name of the requesting cx pod
PodName string `json:"podName,omitempty"`
//DefaultDenyAcl bool indicates whether default deny policy will be present on the pods upon pod creation

Check failure on line 48 in crd/multitenancy/api/v1alpha1/multitenantpodnetworkconfig.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)

Check failure on line 48 in crd/multitenancy/api/v1alpha1/multitenantpodnetworkconfig.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)

Check failure on line 48 in crd/multitenancy/api/v1alpha1/multitenantpodnetworkconfig.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)

Check failure on line 48 in crd/multitenancy/api/v1alpha1/multitenantpodnetworkconfig.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)
DefaultDenyACL bool `json:"defaultDenyACL"`
}

type InterfaceInfo struct {
Expand Down
2 changes: 2 additions & 0 deletions crd/multitenancy/api/v1alpha1/podnetworkinstance.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
// optional for now in case orchestrator uses the deprecated fields
// +kubebuilder:validation:Optional
PodNetworkConfigs []PodNetworkConfig `json:"podNetworkConfigs"`
//DefaultDenyAcl bool indicates whether default deny policy will be present on the pods upon pod creation

Check failure on line 59 in crd/multitenancy/api/v1alpha1/podnetworkinstance.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)

Check failure on line 59 in crd/multitenancy/api/v1alpha1/podnetworkinstance.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)

Check failure on line 59 in crd/multitenancy/api/v1alpha1/podnetworkinstance.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)

Check failure on line 59 in crd/multitenancy/api/v1alpha1/podnetworkinstance.go

View workflow job for this annotation

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

commentFormatting: put a space between `//` and comment text (gocritic)
DefaultDenyACL bool `json:"defaultDenyACL"`
}

// PodNetworkInstanceStatus defines the observed state of PodNetworkInstance
Expand Down
Loading