sigs.k8s.io/cluster-api-provider-azure@v1.14.3/test/e2e/azure_net_pol.go (about)

     1  //go:build e2e
     2  // +build e2e
     3  
     4  /*
     5  Copyright 2020 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package e2e
    21  
    22  import (
    23  	"context"
    24  	"fmt"
    25  	"math/rand"
    26  	"os"
    27  	"time"
    28  
    29  	. "github.com/onsi/ginkgo/v2"
    30  	. "github.com/onsi/gomega"
    31  	corev1 "k8s.io/api/core/v1"
    32  	"k8s.io/client-go/kubernetes"
    33  	"k8s.io/client-go/rest"
    34  	deploymentBuilder "sigs.k8s.io/cluster-api-provider-azure/test/e2e/kubernetes/deployment"
    35  	e2e_namespace "sigs.k8s.io/cluster-api-provider-azure/test/e2e/kubernetes/namespace"
    36  	e2e_networkpolicy "sigs.k8s.io/cluster-api-provider-azure/test/e2e/kubernetes/networkpolicy"
    37  	"sigs.k8s.io/cluster-api/test/framework"
    38  )
    39  
    40  const (
    41  	PolicyDir = "workloads/policies"
    42  )
    43  
    44  // AzureNetPolSpecInput is the input for AzureNetPolSpec.
    45  type AzureNetPolSpecInput struct {
    46  	BootstrapClusterProxy framework.ClusterProxy
    47  	Namespace             *corev1.Namespace
    48  	ClusterName           string
    49  	SkipCleanup           bool
    50  }
    51  
    52  // AzureNetPolSpec implements a test that verifies that the Network Policies Deployed in the managed cluster works.
    53  func AzureNetPolSpec(ctx context.Context, inputGetter func() AzureNetPolSpecInput) {
    54  	var (
    55  		specName     = "azure-netpol"
    56  		input        AzureNetPolSpecInput
    57  		clusterProxy framework.ClusterProxy
    58  		clientset    *kubernetes.Clientset
    59  		config       *rest.Config
    60  	)
    61  
    62  	input = inputGetter()
    63  	Expect(input.BootstrapClusterProxy).NotTo(BeNil(), "Invalid argument. input.BootstrapClusterProxy can't be nil when calling %s spec", specName)
    64  	Expect(input.Namespace).NotTo(BeNil(), "Invalid argument. input.Namespace can't be nil when calling %s spec", specName)
    65  	By("creating a Kubernetes client to the workload cluster")
    66  	clusterProxy = input.BootstrapClusterProxy.GetWorkloadCluster(ctx, input.Namespace.Name, input.ClusterName)
    67  	Expect(clusterProxy).NotTo(BeNil())
    68  	clientset = clusterProxy.GetClientSet()
    69  	Expect(clientset).NotTo(BeNil())
    70  	testTmpDir, err := os.MkdirTemp("/tmp", "azure-test")
    71  	defer os.RemoveAll(testTmpDir)
    72  	Expect(err).NotTo(HaveOccurred())
    73  	config = createRestConfig(ctx, testTmpDir, input.Namespace.Name, input.ClusterName)
    74  	Expect(config).NotTo(BeNil())
    75  
    76  	nsDev, nsProd := "development", "production"
    77  	By("Creating development namespace")
    78  	Log("starting to create dev deployment namespace")
    79  	namespaceDev, err := e2e_namespace.CreateNamespaceDeleteIfExist(ctx, clientset, nsDev, map[string]string{"purpose": "development"})
    80  	Expect(err).NotTo(HaveOccurred())
    81  
    82  	By("Creating production namespace")
    83  	Log("starting to create prod deployment namespace")
    84  	namespaceProd, err := e2e_namespace.CreateNamespaceDeleteIfExist(ctx, clientset, nsProd, map[string]string{"purpose": "production"})
    85  	Expect(err).NotTo(HaveOccurred())
    86  
    87  	By("Creating frontendProd, backend and network-policy pod deployments")
    88  	//nolint:gosec // This is only generating one random number which is used to
    89  	// name resources, so using crypto/rand isn't necessary here.
    90  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
    91  	randInt := r.Intn(99999)
    92  
    93  	// Front end
    94  	frontendLabels := map[string]string{"app": "webapp", "role": "frontend"}
    95  
    96  	// Front end Prod
    97  	frontendProdDeploymentName := fmt.Sprintf("frontend-prod-%v", randInt)
    98  	Log("starting to create frontend-prod deployments")
    99  	frontEndProd := deploymentBuilder.Create("library/nginx:1.21.1", frontendProdDeploymentName, namespaceProd.GetName())
   100  	frontEndProd.AddLabels(frontendLabels)
   101  	frontendProdDeployment, err := frontEndProd.Deploy(ctx, clientset)
   102  	Expect(err).NotTo(HaveOccurred())
   103  
   104  	// Front end Dev
   105  	frontendDevDeploymentName := fmt.Sprintf("frontend-dev-%v", randInt+100000)
   106  	Log("starting to create frontend-dev deployments")
   107  	frontEndDev := deploymentBuilder.Create("library/nginx:1.21.1", frontendDevDeploymentName, namespaceDev.GetName())
   108  	frontEndDev.AddLabels(frontendLabels)
   109  	frontendDevDeployment, err := frontEndDev.Deploy(ctx, clientset)
   110  	Expect(err).NotTo(HaveOccurred())
   111  
   112  	// Backend
   113  	backendDeploymentName := fmt.Sprintf("backend-%v", randInt+200000)
   114  	backendLabels := map[string]string{"app": "webapp", "role": "backend"}
   115  	Log("starting to create backend deployments")
   116  	backendDev := deploymentBuilder.Create("library/nginx:1.21.1", backendDeploymentName, namespaceDev.GetName())
   117  	backendDev.AddLabels(backendLabels)
   118  	backendDeployment, err := backendDev.Deploy(ctx, clientset)
   119  	Expect(err).NotTo(HaveOccurred())
   120  
   121  	// Network policy
   122  	nwpolicyDeploymentName := fmt.Sprintf("network-policy-%v", randInt+300000)
   123  	nwpolicyLabels := map[string]string{"app": "webapp", "role": "any"}
   124  	Log("starting to create network-policy deployments")
   125  	nwpolicy := deploymentBuilder.Create("library/nginx:1.21.1", nwpolicyDeploymentName, namespaceDev.GetName())
   126  	nwpolicy.AddLabels(nwpolicyLabels)
   127  	nwpolicyDeployment, err := nwpolicy.Deploy(ctx, clientset)
   128  	Expect(err).NotTo(HaveOccurred())
   129  
   130  	By("Ensure there is a running frontend-prod pod")
   131  	frontendProdDeploymentInput := framework.WaitForDeploymentsAvailableInput{
   132  		Getter:     deploymentsClientAdapter{client: clientset.AppsV1().Deployments(namespaceProd.GetName())},
   133  		Deployment: frontendProdDeployment,
   134  	}
   135  	framework.WaitForDeploymentsAvailable(ctx, frontendProdDeploymentInput, e2eConfig.GetIntervals(specName, "wait-deployment")...)
   136  
   137  	By("Ensure there is a running frontend-dev pod")
   138  	frontendDevDeploymentInput := framework.WaitForDeploymentsAvailableInput{
   139  		Getter:     deploymentsClientAdapter{client: clientset.AppsV1().Deployments(namespaceDev.GetName())},
   140  		Deployment: frontendDevDeployment,
   141  	}
   142  	framework.WaitForDeploymentsAvailable(ctx, frontendDevDeploymentInput, e2eConfig.GetIntervals(specName, "wait-deployment")...)
   143  
   144  	By("Ensure there is a running backend pod")
   145  	backendDeploymentInput := framework.WaitForDeploymentsAvailableInput{
   146  		Getter:     deploymentsClientAdapter{client: clientset.AppsV1().Deployments(namespaceDev.GetName())},
   147  		Deployment: backendDeployment,
   148  	}
   149  	framework.WaitForDeploymentsAvailable(ctx, backendDeploymentInput, e2eConfig.GetIntervals(specName, "wait-deployment")...)
   150  
   151  	By("Ensure there is a running network-policy pod")
   152  	nwpolicyDeploymentInput := framework.WaitForDeploymentsAvailableInput{
   153  		Getter:     deploymentsClientAdapter{client: clientset.AppsV1().Deployments(namespaceDev.GetName())},
   154  		Deployment: nwpolicyDeployment,
   155  	}
   156  	framework.WaitForDeploymentsAvailable(ctx, nwpolicyDeploymentInput, e2eConfig.GetIntervals(specName, "wait-deployment")...)
   157  
   158  	By("Ensuring we have outbound internet access from the frontend-prod pods")
   159  	frontendProdPods, err := frontEndProd.GetPodsFromDeployment(ctx, clientset)
   160  	Expect(err).NotTo(HaveOccurred())
   161  	e2e_networkpolicy.EnsureOutboundInternetAccess(clientset, config, frontendProdPods)
   162  
   163  	By("Ensuring we have outbound internet access from the frontend-dev pods")
   164  	frontendDevPods, err := frontEndDev.GetPodsFromDeployment(ctx, clientset)
   165  	Expect(err).NotTo(HaveOccurred())
   166  	e2e_networkpolicy.EnsureOutboundInternetAccess(clientset, config, frontendDevPods)
   167  
   168  	By("Ensuring we have outbound internet access from the backend pods")
   169  	backendPods, err := backendDev.GetPodsFromDeployment(ctx, clientset)
   170  	Expect(err).NotTo(HaveOccurred())
   171  	e2e_networkpolicy.EnsureOutboundInternetAccess(clientset, config, backendPods)
   172  
   173  	By("Ensuring we have outbound internet access from the network-policy pods")
   174  	nwpolicyPods, err := nwpolicy.GetPodsFromDeployment(ctx, clientset)
   175  	Expect(err).NotTo(HaveOccurred())
   176  	e2e_networkpolicy.EnsureOutboundInternetAccess(clientset, config, nwpolicyPods)
   177  
   178  	By("Ensuring we have connectivity from network-policy pods to frontend-prod pods")
   179  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, nwpolicyPods, frontendProdPods, true)
   180  
   181  	By("Ensuring we have connectivity from network-policy pods to backend pods")
   182  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, nwpolicyPods, backendPods, true)
   183  
   184  	By("Applying a network policy to deny ingress access to app: webapp, role: backend pods in development namespace")
   185  	nwpolicyName, namespaceE2E, nwpolicyFileName := "backend-deny-ingress", nsDev, "backend-policy-deny-ingress.yaml"
   186  	Logf("starting to applying a network policy %s/%s to deny access to app: webapp, role: backend pods in development namespace", namespaceE2E, nwpolicyName)
   187  	e2e_networkpolicy.ApplyNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E, nwpolicyFileName, PolicyDir)
   188  
   189  	By("Ensuring we no longer have ingress access from the network-policy pods to backend pods")
   190  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, nwpolicyPods, backendPods, false)
   191  
   192  	By("Cleaning up after ourselves")
   193  	Logf("starting to cleaning up network policy %s/%s after ourselves", namespaceE2E, nwpolicyName)
   194  	e2e_networkpolicy.DeleteNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E)
   195  
   196  	By("Applying a network policy to deny egress access in development namespace")
   197  	nwpolicyName, namespaceE2E, nwpolicyFileName = "backend-deny-egress", nsDev, "backend-policy-deny-egress.yaml"
   198  	Logf("starting to applying a network policy %s/%s to deny egress access in development namespace", nsDev, nwpolicyName)
   199  	e2e_networkpolicy.ApplyNetworkPolicy(ctx, clientset, nwpolicyName, nsDev, nwpolicyFileName, PolicyDir)
   200  
   201  	By("Ensuring we no longer have egress access from the network-policy pods to backend pods")
   202  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, nwpolicyPods, backendPods, false)
   203  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, frontendDevPods, backendPods, false)
   204  
   205  	By("Cleaning up after ourselves")
   206  	Logf("starting to cleaning up network policy %s/%s after ourselves", namespaceE2E, nwpolicyName)
   207  	e2e_networkpolicy.DeleteNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E)
   208  
   209  	By("Applying a network policy to allow egress access to app: webapp, role: frontend pods in any namespace from pods with app: webapp, role: backend labels in development namespace")
   210  	nwpolicyName, namespaceE2E, nwpolicyFileName = "backend-allow-egress-pod-label", nsDev, "backend-policy-allow-egress-pod-label.yaml"
   211  	Logf("starting to applying a network policy %s/%s to allow egress access to app: webapp, role: frontend pods in any namespace from pods with app: webapp, role: backend labels in development namespace", namespaceE2E, nwpolicyName)
   212  	e2e_networkpolicy.ApplyNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E, nwpolicyFileName, PolicyDir)
   213  
   214  	By("Ensuring we have egress access from pods with matching labels")
   215  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, backendPods, frontendDevPods, true)
   216  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, backendPods, frontendProdPods, true)
   217  
   218  	By("Ensuring we don't have ingress access from pods without matching labels")
   219  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, backendPods, nwpolicyPods, false)
   220  
   221  	By("Cleaning up after ourselves")
   222  	Logf("starting to cleaning up network policy %s/%s after ourselves", namespaceE2E, nwpolicyName)
   223  	e2e_networkpolicy.DeleteNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E)
   224  
   225  	By("Applying a network policy to allow egress access to app: webapp, role: frontend pods from pods with app: webapp, role: backend labels in same development namespace")
   226  	nwpolicyName, namespaceE2E, nwpolicyFileName = "backend-allow-egress-pod-namespace-label", nsDev, "backend-policy-allow-egress-pod-namespace-label.yaml"
   227  	Logf("starting to applying a network policy %s/%s to allow egress access to app: webapp, role: frontend pods from pods with app: webapp, role: backend labels in same development namespace", namespaceE2E, nwpolicyName)
   228  	e2e_networkpolicy.ApplyNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E, nwpolicyFileName, PolicyDir)
   229  
   230  	By("Ensuring we have egress access from pods with matching labels")
   231  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, backendPods, frontendDevPods, true)
   232  
   233  	By("Ensuring we don't have ingress access from pods without matching labels")
   234  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, backendPods, frontendProdPods, false)
   235  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, backendPods, nwpolicyPods, false)
   236  
   237  	By("Cleaning up after ourselves")
   238  	Logf("starting to cleaning up network policy %s/%s after ourselves", namespaceE2E, nwpolicyName)
   239  	e2e_networkpolicy.DeleteNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E)
   240  
   241  	By("Applying a network policy to only allow ingress access to app: webapp, role: backend pods in development namespace from pods in any namespace with the same labels")
   242  	nwpolicyName, namespaceE2E, nwpolicyFileName = "backend-allow-ingress-pod-label", nsDev, "backend-policy-allow-ingress-pod-label.yaml"
   243  	Logf("starting to applying a network policy %s/%s to only allow ingress access to app: webapp, role: backend pods in development namespace from pods in any namespace with the same labels", namespaceE2E, nwpolicyName)
   244  	e2e_networkpolicy.ApplyNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E, nwpolicyFileName, PolicyDir)
   245  
   246  	By("Ensuring we have ingress access from pods with matching labels")
   247  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, backendPods, backendPods, true)
   248  
   249  	By("Ensuring we don't have ingress access from pods without matching labels")
   250  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, nwpolicyPods, backendPods, false)
   251  
   252  	By("Cleaning up after ourselves")
   253  	Logf("starting to cleaning up network policy %s/%s after ourselves", namespaceE2E, nwpolicyName)
   254  	e2e_networkpolicy.DeleteNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E)
   255  
   256  	By("Applying a network policy to only allow ingress access to app: webapp role:backends in development namespace from pods with label app:webapp, role: frontendProd within namespace with label purpose: development")
   257  	nwpolicyName, namespaceE2E, nwpolicyFileName = "backend-policy-allow-ingress-pod-namespace-label", nsDev, "backend-policy-allow-ingress-pod-namespace-label.yaml"
   258  	Logf("starting to applying a network policy %s/%s to only allow ingress access to app: webapp role:backends in development namespace from pods with label app:webapp, role: frontendProd within namespace with label purpose: development", namespaceE2E, nwpolicyName)
   259  	e2e_networkpolicy.ApplyNetworkPolicy(ctx, clientset, nwpolicyName, namespaceE2E, nwpolicyFileName, PolicyDir)
   260  
   261  	By("Ensuring we don't have ingress access from role:frontend pods in production namespace")
   262  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, frontendProdPods, backendPods, false)
   263  
   264  	By("Ensuring we have ingress access from role:frontend pods in development namespace")
   265  	e2e_networkpolicy.EnsureConnectivityResultBetweenPods(clientset, config, frontendDevPods, backendPods, true)
   266  }