github.phpd.cn/cilium/cilium@v1.6.12/test/k8sT/KafkaPolicies.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package k8sTest 16 17 import ( 18 "context" 19 "fmt" 20 "time" 21 22 "github.com/cilium/cilium/api/v1/models" 23 . "github.com/cilium/cilium/test/ginkgo-ext" 24 "github.com/cilium/cilium/test/helpers" 25 26 . "github.com/onsi/gomega" 27 ) 28 29 var _ = Describe("K8sKafkaPolicyTest", func() { 30 31 var ( 32 kubectl *helpers.Kubectl 33 microscopeErr error 34 microscopeCancel = func() error { return nil } 35 backgroundCancel context.CancelFunc = func() { return } 36 backgroundError error 37 l7Policy = helpers.ManifestGet("kafka-sw-security-policy.yaml") 38 demoPath = helpers.ManifestGet("kafka-sw-app.yaml") 39 kafkaApp = "kafka" 40 backupApp = "empire-backup" 41 empireHqApp = "empire-hq" 42 outpostApp = "empire-outpost" 43 apps = []string{kafkaApp, backupApp, empireHqApp, outpostApp} 44 appPods = map[string]string{} 45 topicEmpireAnnounce = "empire-announce" 46 topicDeathstarPlans = "deathstar-plans" 47 topicTest = "test-topic" 48 49 prodHqAnnounce = `sh -c "echo 'Happy 40th Birthday to General Tagge' | ./kafka-produce.sh --topic empire-announce"` 50 conOutpostAnnoune = `sh -c "./kafka-consume.sh --topic empire-announce --from-beginning --max-messages 1"` 51 prodHqDeathStar = `sh -c "echo 'deathstar reactor design v3' | ./kafka-produce.sh --topic deathstar-plans"` 52 conOutDeathStar = `sh -c "./kafka-consume.sh --topic deathstar-plans --from-beginning --max-messages 1"` 53 prodBackAnnounce = `sh -c "echo 'Happy 40th Birthday to General Tagge' | ./kafka-produce.sh --topic empire-announce"` 54 prodOutAnnounce = `sh -c "echo 'Vader Booed at Empire Karaoke Party' | ./kafka-produce.sh --topic empire-announce"` 55 ) 56 57 AfterFailed(func() { 58 kubectl.CiliumReport(helpers.KubeSystemNamespace, 59 "cilium service list", 60 "cilium endpoint list") 61 }) 62 63 AfterAll(func() { 64 kubectl.CloseSSHClient() 65 }) 66 67 Context("Kafka Policy Tests", func() { 68 createTopicCmd := func(topic string) string { 69 return fmt.Sprintf("/opt/kafka_2.11-0.10.1.0/bin/kafka-topics.sh --create "+ 70 "--zookeeper localhost:2181 --replication-factor 1 "+ 71 "--partitions 1 --topic %s", topic) 72 } 73 74 createTopic := func(topic string, pod string) error { 75 return kubectl.ExecKafkaPodCmd(helpers.DefaultNamespace, pod, createTopicCmd(topic)) 76 } 77 78 // WaitKafkaBroker waits for the broker to be ready, by executing 79 // a command repeatedly until it succeeds, or a timeout occurs 80 waitForKafkaBroker := func(pod string, cmd string) error { 81 body := func() bool { 82 err := kubectl.ExecKafkaPodCmd(helpers.DefaultNamespace, pod, cmd) 83 if err != nil { 84 return false 85 } 86 return true 87 } 88 err := helpers.WithTimeout(body, "Kafka Broker not ready", &helpers.TimeoutConfig{Timeout: helpers.HelperTimeout}) 89 return err 90 } 91 92 waitForDNSResolution := func(pod, service string) error { 93 body := func() bool { 94 dnsLookupCmd := fmt.Sprintf("nslookup %s", service) 95 res := kubectl.ExecPodCmd(helpers.DefaultNamespace, pod, dnsLookupCmd) 96 97 if !res.WasSuccessful() { 98 return false 99 } 100 return true 101 } 102 err := helpers.WithTimeout(body, fmt.Sprintf("unable to resolve DNS for service %s in pod %s", service, pod), &helpers.TimeoutConfig{Timeout: 30 * time.Second}) 103 return err 104 } 105 106 JustBeforeEach(func() { 107 microscopeErr, microscopeCancel = kubectl.MicroscopeStart() 108 Expect(microscopeErr).To(BeNil(), "Microscope cannot be started") 109 110 backgroundCancel, backgroundError = kubectl.BackgroundReport("uptime") 111 Expect(backgroundError).To(BeNil(), "Cannot start background report process") 112 }) 113 114 JustAfterEach(func() { 115 kubectl.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration) 116 Expect(microscopeCancel()).To(BeNil(), "cannot stop microscope") 117 backgroundCancel() 118 }) 119 120 AfterEach(func() { 121 // On aftereach don't make assertions to delete all. 122 _ = kubectl.Delete(demoPath) 123 _ = kubectl.Delete(l7Policy) 124 125 ExpectAllPodsTerminated(kubectl) 126 }) 127 128 BeforeAll(func() { 129 kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger) 130 DeployCiliumAndDNS(kubectl) 131 132 kubectl.ApplyDefault(demoPath) 133 err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=kafkaTestApp", helpers.HelperTimeout) 134 Expect(err).Should(BeNil(), "Kafka Pods are not ready after timeout") 135 136 err = kubectl.WaitForKubeDNSEntry("kafka-service", helpers.DefaultNamespace) 137 Expect(err).To(BeNil(), "DNS entry of kafka-service is not ready after timeout") 138 139 err = kubectl.CiliumEndpointWaitReady() 140 Expect(err).To(BeNil(), "Endpoints are not ready after timeout") 141 142 appPods = helpers.GetAppPods(apps, helpers.DefaultNamespace, kubectl, "app") 143 144 By("Wait for Kafka broker to be up") 145 err = waitForKafkaBroker(appPods[kafkaApp], createTopicCmd(topicTest)) 146 Expect(err).To(BeNil(), "Timeout: Kafka cluster failed to come up correctly") 147 }) 148 149 It("KafkaPolicies", func() { 150 By("Creating new kafka topic %s", topicEmpireAnnounce) 151 err := createTopic(topicEmpireAnnounce, appPods[kafkaApp]) 152 Expect(err).Should(BeNil(), "Failed to create topic empire-announce") 153 154 By("Creating new kafka topic %s", topicDeathstarPlans) 155 err = createTopic(topicDeathstarPlans, appPods[kafkaApp]) 156 Expect(err).Should(BeNil(), "Failed to create topic deathstar-plans") 157 158 By("Waiting for DNS to resolve within pods for kafka-service") 159 err = waitForDNSResolution(appPods[empireHqApp], "kafka-service") 160 Expect(err).Should(BeNil(), "Failed to resolve kafka-service DNS entry in pod %s", appPods[empireHqApp]) 161 err = waitForDNSResolution(appPods[outpostApp], "kafka-service") 162 Expect(err).Should(BeNil(), "Failed to resolve kafka-service DNS entry in pod %s", appPods[outpostApp]) 163 164 By("Testing basic Kafka Produce and Consume") 165 // We need to produce first, since consumer script waits for 166 // some messages to be already there by the producer. 167 168 err = kubectl.ExecKafkaPodCmd( 169 helpers.DefaultNamespace, appPods[empireHqApp], fmt.Sprintf(prodHqAnnounce)) 170 Expect(err).Should(BeNil(), "Failed to produce to empire-hq on topic empire-announce") 171 172 err = kubectl.ExecKafkaPodCmd( 173 helpers.DefaultNamespace, appPods[outpostApp], fmt.Sprintf(conOutpostAnnoune)) 174 Expect(err).Should(BeNil(), "Failed to consume from outpost on topic empire-announce") 175 176 err = kubectl.ExecKafkaPodCmd( 177 helpers.DefaultNamespace, appPods[empireHqApp], fmt.Sprintf(prodHqDeathStar)) 178 Expect(err).Should(BeNil(), "Failed to produce to empire-hq on topic deathstar-plans") 179 180 err = kubectl.ExecKafkaPodCmd( 181 helpers.DefaultNamespace, appPods[outpostApp], fmt.Sprintf(conOutDeathStar)) 182 Expect(err).Should(BeNil(), "Failed to consume from outpost on topic deathstar-plans") 183 184 err = kubectl.ExecKafkaPodCmd( 185 helpers.DefaultNamespace, appPods[backupApp], fmt.Sprintf(prodBackAnnounce)) 186 Expect(err).Should(BeNil(), "Failed to produce to backup on topic empire-announce") 187 188 err = kubectl.ExecKafkaPodCmd( 189 helpers.DefaultNamespace, appPods[outpostApp], fmt.Sprintf(prodOutAnnounce)) 190 Expect(err).Should(BeNil(), "Failed to produce to outpost on topic empire-announce") 191 192 By("Apply L7 kafka policy and wait") 193 194 _, err = kubectl.CiliumPolicyAction( 195 helpers.DefaultNamespace, l7Policy, 196 helpers.KubectlApply, helpers.HelperTimeout) 197 Expect(err).To(BeNil(), "L7 policy cannot be imported correctly") 198 199 By("validate that CEP is updated with correct enforcement mode") 200 201 desiredPolicyStatus := map[string]models.EndpointPolicyEnabled{ 202 backupApp: models.EndpointPolicyEnabledNone, 203 empireHqApp: models.EndpointPolicyEnabledNone, 204 kafkaApp: models.EndpointPolicyEnabledBoth, 205 outpostApp: models.EndpointPolicyEnabledNone, 206 } 207 208 body := func() bool { 209 for app, policy := range desiredPolicyStatus { 210 cep := kubectl.CepGet(helpers.DefaultNamespace, appPods[app]) 211 if cep == nil { 212 return false 213 } 214 state := models.EndpointPolicyEnabledNone 215 switch { 216 case cep.Policy.Egress.Enforcing && cep.Policy.Ingress.Enforcing: 217 state = models.EndpointPolicyEnabledBoth 218 case cep.Policy.Egress.Enforcing: 219 state = models.EndpointPolicyEnabledIngress 220 case cep.Policy.Ingress.Enforcing: 221 state = models.EndpointPolicyEnabledEgress 222 } 223 224 if state != policy { 225 return false 226 } 227 } 228 return true 229 } 230 err = helpers.WithTimeout(body, "CEP policy enforcement", &helpers.TimeoutConfig{Timeout: helpers.HelperTimeout}) 231 Expect(err).To(BeNil(), "CEP not updated with correct policy enforcement") 232 233 By("Testing Kafka L7 policy enforcement status") 234 err = kubectl.ExecKafkaPodCmd( 235 helpers.DefaultNamespace, appPods[empireHqApp], fmt.Sprintf(prodHqAnnounce)) 236 Expect(err).Should(BeNil(), "Failed to produce to empire-hq on topic empire-announce") 237 238 err = kubectl.ExecKafkaPodCmd( 239 helpers.DefaultNamespace, appPods[outpostApp], fmt.Sprintf(conOutpostAnnoune)) 240 Expect(err).Should(BeNil(), "Failed to consume from outpost on topic empire-announce") 241 242 err = kubectl.ExecKafkaPodCmd( 243 helpers.DefaultNamespace, appPods[empireHqApp], fmt.Sprintf(prodHqDeathStar)) 244 Expect(err).Should(BeNil(), "Failed to produce from empire-hq on topic deathstar-plans") 245 246 err = kubectl.ExecKafkaPodCmd( 247 helpers.DefaultNamespace, appPods[outpostApp], fmt.Sprintf(conOutpostAnnoune)) 248 Expect(err).Should(BeNil(), "Failed to consume from outpost on topic empire-announce") 249 250 err = kubectl.ExecKafkaPodCmd( 251 helpers.DefaultNamespace, appPods[backupApp], fmt.Sprintf(prodBackAnnounce)) 252 Expect(err).Should(HaveOccurred(), " Produce to backup on topic empire-announce should have been denied") 253 254 err = kubectl.ExecKafkaPodCmd( 255 helpers.DefaultNamespace, appPods[outpostApp], fmt.Sprintf(conOutDeathStar)) 256 Expect(err).Should(HaveOccurred(), " Consume from outpost on topic deathstar-plans should have been denied") 257 258 err = kubectl.ExecKafkaPodCmd( 259 helpers.DefaultNamespace, appPods[outpostApp], fmt.Sprintf(prodOutAnnounce)) 260 Expect(err).Should(HaveOccurred(), "Produce to outpost on topic empire-announce should have been denied") 261 }) 262 }) 263 })