Saturday 24 September 2022




Figure 9.8 The sequence of events that happen when a client (curl) makes a request to place an order. Note that steps 4 and 5 can happen in parallel because they’re on two independent processes. 

The Buying History microservice received the order details via the Kafka topic ORDERS. On receiving this event, it executes its logic to track the purchase history of the customer. In this particular case, it prints a message to the console saying it received the order event and processed it. Figure 9.8 illustrates the sequence of events.


             Using TLS to protect data in transit

Listing 9.6 Generated keys and certificates

├──buyinghistory
│   ├── buyinghistory.jks    
│   └── truststore.jks       
├── ca
│   ├── ca_cert.pem          
│   └── ca_key.pem           
├── kafka_server
│   ├── kafka_server.jks     
│   └── truststore.jks       
├── orderprocessing
     ├── orderprocessing.jks  
     └── truststore.jks       

 1 The keystore that carries the private key and the CA signed certificate of the Buying History microservice

 2. The keystore that carries the public certificate of the CA

 3. The public certificate of the CA

 4. The private key of the CA

 5. The keystore that carries the private key and the CA signed certificate of the Kafka server

 6. The keystore that carries the public certificate of the CA

 7. The keystore that carries the private key and the CA signed certificate of the Order Processing microservice

 8. The keystore that carries the public certificate of the CA


To enable TLS on Kafka, first make sure the Kafka server is shut down if it’s already running, but keep the ZooKeeper server running (from section 9.2). You need to press Ctrl-C on your keyboard on the respective command-line terminal process. After the process shuts down, use your command-line client tool or file explorer to navigate to the kafka_home/config directory. Open the server.properties file by using your text editor of choice and add the following properties to the file.

Listing 9.7 Content of server.properties file

listeners=PLAINTEXT://:9092,SSL://:9093         
ssl.keystore.location=kafka_server.jks   
ssl.keystore.password=password
ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1
ssl.secure.random.implementation=SHA1PRNG

 1. Tells the Kafka server to listen on ports 9092 for plaintext (nonsecure) connections and port 9093 for secure connections

 2. Provides the absolute path to the kafka_server.jks file. Make sure to change this value appropriately.


              Configuring TLS on the microservices

In this section, we discuss how to enable TLS on our Order Processing and Buying History microservices. 

When configuring keystores with the Order Processing and Buying History microservices, we need to consider two things:

  • Enabling HTTPS for the Order Processing microservice so the client applications that talk to the Order Processing microservice must use HTTPS. We don’t need to do the same for the Buying History microservice because we don’t expose it over HTTP.

  • Configuring both Order Processing and Buying History microservices to trust the public certificate of the CA that signed the public certificate of the Kafka server. The Order Processing microservice connects to the Kafka server to publish messages, and the Buying History microservice connects to the Kafka server to read messages. Both of these communications now happen over TLS, and both the microservices have to trust the CA who issued the public certificate of the Kafka server.

Also check the values of server.ssl.key-store and server.ssl.key-store-password properties. These two properties enable HTTPS transport for the Order Processing microservice.

Listing 9.8 Content of application.properties file

server.ssl.key-store: orderprocessing.jks               
server.ssl.key-store-password: manning123               
spring.kafka.bootstrap-servers:localhost:9093           
spring.kafka.properties.security.protocol=SSL           
spring.kafka.properties.ssl.endpoint
                       .identification.algorithm=       
spring.kafka.ssl
            .trust-store-location=file:truststore.jks   
spring.kafka.ssl.trust-store-password=manning123        

spring.kafka.ssl.trust-store-type=JKS                   

 1. The location of the keystore that carries the keys to enable HTTPS communication

 2. The password of the keystore

 3. Instructs the microservice to connect to the TLS port (9093) of Kafka. If noport is specified, the microserviceconnects to the default Kafka port 9092, which is the plaintext port (no TLS).

 4. Sets the protocol to SSL, which enables TLS communication

 5. By leaving this empty, we effectively get our microservice to ignore the hostname verification of the server certificate. In a production deployment, you shouldn’t do this.

 6. The location of the keystore that carries the CA’s public certificate

 7. The password of the trust store

 8. The type of trust store

Using  Using mTLS for authentication

Above we looked at enabling TLS between the microservices and the Kafka server. In this section, we discuss how to protect communications between the Order Processing microservice and the Kafka server, as well as the communications between the Buying History microservice and the Kafka server with mTLS for client authentication.

By enabling TLS between the microservices and Kafka, we ensure that the data being transmitted over the network among these parties is encrypted. Nobody sniffing into the network would be able to read the data being transmitted unless they had access to the server’s (Kafka) private key. By enabling TLS, we also made sure that the microservices (clients) are connected to the intended/trusted Kafka server and not to anyone or anything pretending to be the server.

One problem that still remains, however, is that anyone that has network access to the Kafka server and that trusts the CA that signed Kafka’s certificate can publish and receive events to and from the Kafka server. For example, anyone could impersonate the Order Processing microservice and send bogus order events to Kafka. Figure 9.9 illustrates this scenario.

Figure 9.9 The Bogus microservice impersonates the Order Processing microservice by sending order events to Kafka. This makes the other microservices process these order events. Kafka needs to explicitly allow only the trusted microservices to connect to it.

Here, the Bogus microservice is also sending events to Kafka, which would trigger false events in the system and make the other microservices act on it. This would cause our system to break. To prevent this from happening, we need to make sure that only the trusted Order Processing microservice and other trusted microservices are permitted to send and receive events from Kafka.

                 Controlling access to Kafka topics with ACLs

we discussed how to enable client authentication using mTLS. We discussed how we could control connections to the Kafka server by using mTLS. We made sure that only trusted clients could connect to Kafka. We used mutually trusted certificates both on the client (microservice) and the Kafka server to achieve this. We did that by getting a mutually trusted CA to sign the certificates of both parties (the client and the server).

We now want to get to a state where only selected microservices are given selective permissions to Kafka topics. For example, we need to ensure that only the Order Processing microservice can publish events into the ORDERS topic in Kafka, and only the Buying History microservice should be permitted to read events from the ORDERS topic. We can’t achieve this with mTLS only. Because the Buying History microservice from section 9.6 was granted connection rights through mTLS, it can technically publish events to the ORDERS topic even though the code examples we used didn’t. Figure 9.10 illustrates this scenario.

Figure 9.10 The Buying History microservice sends events to Kafka topics. Any microservice that's trusted by Kafka can technically send events to its topics unless restricted by ACLs. These events are delivered to microservices that are subscribed to the Kafka topic unless they have been restricted by ACLs.

Let’s take a look at how to prevent this from happening. What we have so far achieved in this chapter is client and server authentication. To enforce more fine-grained access control on Kafka topics, we need to implement authorization on Kafka. Kafka provides a way of implementing authorization using ACLs. An ACL is basically a rule on Kafka that either permits or denies a particular entity from performing an action on a Kafka resource. Kafka ACLs are defined in the following format:

Principal P is [Allowed/Denied] Operation O From Host H 
on any Resource R matching ResourcePattern RP

where

  • Principal represents the entity (the client) that attempts to perform an operation.

  • Operation can be any one of several actions including creating a topic, writing events to a topic, reading events from a topic, and so on.

  • Host is the IP address/hostname of the Kafka client.

  • Resource is an entity on Kafka, such as a topic, a consumer group, and so on.

  • ResourcePattern is a pattern that’s used to identify the resources on which the rule is to be applied.








No comments:

Post a Comment