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 CNS Changes #3286

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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: 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"
rbtr marked this conversation as resolved.
Show resolved Hide resolved
"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
37 changes: 29 additions & 8 deletions cns/middlewares/k8sSwiftV2.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ var _ cns.IPConfigsHandlerMiddleware = (*K8sSWIFTv2Middleware)(nil)
// 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)

logger.Printf("defaultDenyACLbool value is: %v", defaultDenyACLbool)

if respCode != types.Success {
return &cns.IPConfigsResponse{
Expand All @@ -55,6 +57,19 @@ func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa
if !req.SecondaryInterfacesExist {
return ipConfigsResp, err
}

// ipConfigsResp has infra IP configs -> if defaultDenyACLbool is enabled, add the default deny acl's pn the infra IP configs
for i := range ipConfigsResp.PodIPInfo {
ipInfo := &ipConfigsResp.PodIPInfo[i]
Comment on lines +62 to +63
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to do:

Suggested change
for i := range ipConfigsResp.PodIPInfo {
ipInfo := &ipConfigsResp.PodIPInfo[i]
for _, ipInfo := range ipConfigsResp.PodIPInfo {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, there are 2 reasons why I did not go that route

  • I see the following error: rangeValCopy: each iteration copies 256 bytes (consider pointers or indexing) (gocritic)

image

  • This line of code: _, ipInfo := range ipConfigsResp.PodIPInfo creates a copy of ipInfo and &ipInfo creates a pointer to the copy; however, does not change the slice itself.

Please feel free to correct me on this, but that was my thinking.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like premature optimization to me. I'd prefer the more readable suggestion unless we can point at some benchmarks / profiling that proves this large copy is a performance bottleneck.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timraymond, can you please elaborate on which readable suggestion you are referring to?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @rejain456 , when I refer to "the suggestion" here, I mean the code suggestion in the top comment here: #3286 (comment)

Copy link
Contributor Author

@rejain456 rejain456 Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timraymond , got it thanks for clarifying. Regarding that I believe this line of code: _, ipInfo := range ipConfigsResp.PodIPInfo creates a copy of ipInfo and &ipInfo creates a pointer to the copy; however, does not change the slice itself. In that case, the list PodIPInfo won't get changed. Whereas the line:
for i := range ipConfigsResp.PodIPInfo { ipInfo := &ipConfigsResp.PodIPInfo[i] creates a pointer to the original PodIPInfo list and will change the properties in it.

Please let me know if any part of that is incorrect

// there will be no pod connectivity to and from those pods
if defaultDenyACLbool && ipInfo.NICType == cns.InfraNIC {
err = addDefaultDenyACL(ipInfo)
if err != nil {
logger.Errorf("failed to add default deny acl's for pod %v with err %v", podInfo.Name(), err)
rejain456 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

// If the pod is v2, get the infra IP configs from the handler first and then add the SWIFTv2 IP config
defer func() {
// Release the default IP config if there is an error
Expand Down Expand Up @@ -102,19 +117,21 @@ func (k *K8sSWIFTv2Middleware) IPConfigsRequestHandlerWrapper(defaultHandler, fa

// 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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not excited about adding a fourth return value here, and I generally don't like to return bools (since they carry no documentation about their meaning).

I would almost be of a mind to do the k.Cli.Get(ctx, mtpncNamespacedName, &mtpnc) to find out the status of the defaultDenyACL one level up the call stack where we want to use that value, but I understand that incurs a penalty for the second network call to the api server.

The only alternate proposal I have is caching these values on *K8sSWIFTv2Middleware, but all the usual hazards of caching apply here. For something applying network policy, I'm leery of doing this.

I suppose this is okay for now unless we can think of an alternative that avoids it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method has become too overloaded. validate- means tell me if this input is valid. It should only return a 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
Expand All @@ -126,12 +143,16 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
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
}

// copying defaultDenyACL bool from mtpnc
defaultDenyACLbool = mtpnc.Status.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 +161,7 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
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 +175,7 @@ func (k *K8sSWIFTv2Middleware) validateIPConfigsRequest(ctx context.Context, req
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) assignSubnetPrefixLengthFields(_ *cns.PodIpInfo,
}

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

func addDefaultDenyACL(_ *cns.PodIpInfo) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we shouldn't call this from common code if it requires a stub in an _os file. we should be able to abstract in such a way that we don't do this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually ok with this, I feel it's better to have an os stub than to branch in the common code based on runtime.GOOS

Copy link
Contributor

@rbtr rbtr Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want us to check runtime.GOOS either. But we can do a better job using the _<os>.go pattern...I feel like I have done this several times recently, but I can't find a good example immediately.

At k8sSwiftV2_linux.go L105 right above here, there's a stub for addDefaultRoute which noops. If we only need to set a default route on Windows, putting addDefaultRoute in the OS abstraction is the wrong place - what are we doing when we need to addDefaultRoute? That's the thing that actually has different behavior per-OS, and so that's the thing that should be in the OS specific files.

If we need these stubs, the abstraction is wrong...or effectively doesn't exist. We're not abstracting away the OSes, we're actually coding them all together and branching implicitly based on the GOOS. The if just moves out of the code and in to my head, because now I need to know that if GOOS=linux then this method call is noop when I'm reading the common calling code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the thing that actually has different behavior per-OS, and so that's the thing that should be in the OS specific files.

While this is probably true, I don't want this PR to become too much about refactoring that. There's a lot of stuff in the calling code which we'd have to duplicate and/or refactor which I would rather not do now, and I feel this doesn't put us in much worse a situation for when (if) we do take up that work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk, if there's only one OS that needs special handling, and the rest are all NOPs, I find runtime.GOOS more readable. It works better with static analysis too, since you don't need to set GOOS for the toolchain to realize there is an entire separate implementation.

Now if we had wholly different implementations, each with their own considerations, I'd consider build tags more necessary.

Copy link
Contributor

@rbtr rbtr Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works if the special handling is entirely your code and doesn't work if it's platform specific things like using registry package which is compiled for and can only be referenced from code compiled for Windows. It doesn't work here because the special extra logic for Windows is interacting with HCN and hcsshim/hcn is not importable outside of a Windows built file.
We do a lot of this - Linux iptables, netns, etc vs Windows HCS, registry, etc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough--if there's compile-time reasons, that's certainly a good reason. I guess lately I've seen a few instances where it's just exec.Cmds for either powershell.exe or their Linux equivalent. In those circumstances, the specific string can be decided at runtime.

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
59 changes: 59 additions & 0 deletions cns/middlewares/k8sSwiftV2_windows.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package middlewares

import (
"encoding/json"

"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 +62,58 @@
}
podIPInfo.Routes = append(podIPInfo.Routes, route)
}

// append the default deny acl's to the list defaultDenyACL field in podIpInfo
func 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: func parameter podIpInfo should be podIPInfo (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: func parameter podIpInfo should be podIPInfo (revive)
blockEgressACL, err := getDefaultDenyACLPolicy(hcn.DirectionTypeOut)
if err != nil {
return errors.Wrap(err, "Failed to create default deny ACL policy egress")
}

blockIngressACL, err := getDefaultDenyACLPolicy(hcn.DirectionTypeIn)
if err != nil {
return errors.Wrap(err, "Failed to create default deny ACL policy ingress")
}

additionalArgs := []cni.KVPair{
{
Name: "EndpointPolicy",
Value: blockEgressACL,
},
{
Name: "EndpointPolicy",
Value: blockIngressACL,
},
}

podIpInfo.DefaultDenyACL = append(podIpInfo.DefaultDenyACL, additionalArgs...)

return nil
}

// create the default deny acl's that need to be added to the list defaultDenyACL field in podIpInfo
func getDefaultDenyACLPolicy(direction hcn.DirectionType) ([]byte, error) {
const DefaultDenyPriority = 10000
const policyType = "ACL"
rejain456 marked this conversation as resolved.
Show resolved Hide resolved
type DefaultDenyACL struct {
Type string `json:"Type"`
Action hcn.ActionType `json:"Action"`
Direction hcn.DirectionType `json:"Direction"`
Priority int `json:"Priority"`
}

denyACL := DefaultDenyACL{
Type: policyType,
Action: hcn.ActionTypeBlock,
Direction: direction,
Priority: DefaultDenyPriority,
}

denyACLJSON, err := json.Marshal(denyACL)

if err != nil {
return nil, errors.Wrap(err, "error marshalling default deny policy to json")
}

return denyACLJSON, nil
}
73 changes: 73 additions & 0 deletions cns/middlewares/k8sSwiftV2_windows_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package middlewares

import (
"encoding/json"
"reflect"
"testing"

"github.com/Azure/azure-container-networking/cni"
"github.com/Azure/azure-container-networking/cns"
"github.com/Azure/azure-container-networking/cns/middlewares/mock"
"github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1"
"github.com/stretchr/testify/require"
"gotest.tools/v3/assert"
)

Expand Down Expand Up @@ -100,3 +103,73 @@ func TestAddDefaultRoute(t *testing.T) {
t.Errorf("got '%+v', expected '%+v'", ipInfo.Routes, expectedRoutes)
}
}

func TestAddDefaultDenyACL(t *testing.T) {
valueOut := []byte(`{
"Type": "ACL",
"Action": "Block",
"Direction": "Out",
"Priority": 10000
}`)

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

expectedDefaultDenyACL := []cni.KVPair{
{
Name: "EndpointPolicy",
Value: valueOut,
},
{
Name: "EndpointPolicy",
Value: valueIn,
},
}

podIPInfo := cns.PodIpInfo{
PodIPConfig: cns.IPSubnet{
IPAddress: "20.240.1.242",
PrefixLength: 32,
},
NICType: cns.DelegatedVMNIC,
MacAddress: "12:34:56:78:9a:bc",
}

err := addDefaultDenyACL(&podIPInfo)
assert.Equal(t, err, nil)

// Normalize both slices so there is no extra spacing, new lines, etc
normalizedExpected := normalizeKVPairs(t, expectedDefaultDenyACL)
normalizedActual := normalizeKVPairs(t, podIPInfo.DefaultDenyACL)
if !reflect.DeepEqual(normalizedExpected, normalizedActual) {
t.Errorf("got '%+v', expected '%+v'", podIPInfo.DefaultDenyACL, expectedDefaultDenyACL)
}
}

// normalizeKVPairs normalizes the JSON values in the KV pairs by unmarshaling them into a map, then marshaling them back to compact JSON to remove any extra space, new lines, etc
func normalizeKVPairs(t *testing.T, kvPairs []cni.KVPair) []cni.KVPair {
normalized := make([]cni.KVPair, len(kvPairs))

for i, kv := range kvPairs {
var unmarshaledValue map[string]interface{}
// Unmarshal the Value into a map
err := json.Unmarshal(kv.Value, &unmarshaledValue)
require.NoError(t, err, "Failed to unmarshal JSON value")

// Marshal it back to compact JSON
normalizedValue, err := json.Marshal(unmarshaledValue)
require.NoError(t, err, "Failed to re-marshal JSON value")

// Replace Value with the normalized compact JSON
normalized[i] = cni.KVPair{
Name: kv.Name,
Value: normalizedValue,
}
}

return normalized
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ type MultitenantPodNetworkConfigStatus struct {
// InterfaceInfos describes all of the network container goal state for this Pod
// +kubebuilder:validation:Optional
InterfaceInfos []InterfaceInfo `json:"interfaceInfos,omitempty"`
// DefaultDenyAcl bool indicates whether default deny policy will be present on the pods upon pod creation
DefaultDenyACL bool `json:"defaultDenyACL"`
}

func init() {
Expand Down
3 changes: 3 additions & 0 deletions crd/multitenancy/api/v1alpha1/podnetworkinstance.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ type PodNetworkInstanceSpec struct {
// 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
// +kubebuilder:default=false
DefaultDenyACL bool `json:"defaultDenyACL"`
}

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