You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by ur...@apache.org on 2022/09/20 12:02:08 UTC

[pulsar-site] branch main updated: Docs sync done from apache/pulsar(#37f0a2d)

This is an automated email from the ASF dual-hosted git repository.

urfree pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pulsar-site.git


The following commit(s) were added to refs/heads/main by this push:
     new 8e19ceb994a Docs sync done from apache/pulsar(#37f0a2d)
8e19ceb994a is described below

commit 8e19ceb994abfc24697e282c3210e9ca5106dd42
Author: Pulsar Site Updater <de...@pulsar.apache.org>
AuthorDate: Tue Sep 20 12:02:02 2022 +0000

    Docs sync done from apache/pulsar(#37f0a2d)
---
 .../website-next/docs/administration-dashboard.md  |   2 +-
 site2/website-next/docs/client-libraries-node.md   | 156 +-------
 site2/website-next/docs/client-libraries-python.md |  98 +----
 site2/website-next/docs/cookbooks-encryption.md    | 396 ++++++++++++++-------
 site2/website-next/docs/io-connectors.md           |   8 +-
 site2/website-next/docs/io-mongo-source.md         |  55 +++
 site2/website-next/docs/security-authorization.md  |   2 +-
 site2/website-next/docs/security-encryption.md     | 302 +---------------
 site2/website-next/docs/security-overview.md       |  42 ++-
 .../static/assets/pulsar-encryption.svg            |   1 +
 10 files changed, 392 insertions(+), 670 deletions(-)

diff --git a/site2/website-next/docs/administration-dashboard.md b/site2/website-next/docs/administration-dashboard.md
index c722097cbf3..0bee7be44ce 100644
--- a/site2/website-next/docs/administration-dashboard.md
+++ b/site2/website-next/docs/administration-dashboard.md
@@ -62,6 +62,6 @@ bin/pulsar standalone --advertised-address 1.2.3.4
 
 :::note
 
-Currently, only Pulsar Token [authentication](security-overview.md#authentication-providers) is supported.
+Currently, only Pulsar Token [authentication](security-overview.md#authentication) is supported.
 
 :::
\ No newline at end of file
diff --git a/site2/website-next/docs/client-libraries-node.md b/site2/website-next/docs/client-libraries-node.md
index ab38c04ee2f..e0739763bdb 100644
--- a/site2/website-next/docs/client-libraries-node.md
+++ b/site2/website-next/docs/client-libraries-node.md
@@ -451,158 +451,4 @@ The following static methods are available for the message id object:
 
 ## End-to-end encryption
 
-[End-to-end encryption](/cookbooks-encryption.md#docsNav) allows applications to encrypt messages at producers and decrypt at consumers.
-
-### Configuration
-
-If you want to use the end-to-end encryption feature in the Node.js client, you need to configure `publicKeyPath` for producer and `privateKeyPath` for consumers.
-
-```conf
-publicKeyPath: "./public.pem"
-privateKeyPath: "./private.pem"
-```
-
-### Tutorial
-
-This section provides step-by-step instructions on how to use the end-to-end encryption feature in the Node.js client.
-
-**Prerequisite**
-
-- Pulsar C++ client 2.7.1 or later
-
-**Step**
-
-1. Create both public and private key pairs.
-
-   **Input**
-
-   ```shell
-   openssl genrsa -out private.pem 2048
-   openssl rsa -in private.pem -pubout -out public.pem
-   ```
-
-2. Create a producer to send encrypted messages.
-
-   **Input**
-
-   ```javascript
-   const Pulsar = require('pulsar-client');
-
-   (async () => {
-     // Create a client
-     const client = new Pulsar.Client({
-       serviceUrl: 'pulsar://localhost:6650',
-       operationTimeoutSeconds: 30,
-     });
-
-     // Create a producer
-     const producer = await client.createProducer({
-       topic: 'persistent://public/default/my-topic',
-       sendTimeoutMs: 30000,
-       batchingEnabled: true,
-       publicKeyPath: "./public.pem",
-       encryptionKey: "encryption-key"
-     });
-
-     console.log(producer.ProducerConfig)
-     // Send messages
-     for (let i = 0; i < 10; i += 1) {
-       const msg = `my-message-${i}`;
-       producer.send({
-         data: Buffer.from(msg),
-       });
-       console.log(`Sent message: ${msg}`);
-     }
-     await producer.flush();
-
-     await producer.close();
-     await client.close();
-   })();
-   ```
-
-3. Create a consumer to receive encrypted messages.
-
-   **Input**
-
-   ```javascript
-   const Pulsar = require('pulsar-client');
-
-   (async () => {
-     // Create a client
-     const client = new Pulsar.Client({
-       serviceUrl: 'pulsar://172.25.0.3:6650',
-       operationTimeoutSeconds: 30
-     });
-
-     // Create a consumer
-     const consumer = await client.subscribe({
-       topic: 'persistent://public/default/my-topic',
-       subscription: 'sub1',
-       subscriptionType: 'Shared',
-       ackTimeoutMs: 10000,
-       privateKeyPath: "./private.pem"
-     });
-
-     console.log(consumer)
-     // Receive messages
-     for (let i = 0; i < 10; i += 1) {
-       const msg = await consumer.receive();
-       console.log(msg.getData().toString());
-       consumer.acknowledge(msg);
-     }
-
-     await consumer.close();
-     await client.close();
-   })();
-   ```
-
-4. Run the consumer to receive encrypted messages.
-
-   **Input**
-
-   ```shell
-   node consumer.js
-   ```
-
-5. In a new terminal tab, run the producer to produce encrypted messages.
-
-   **Input**
-
-   ```shell
-   node producer.js
-   ```
-
-   Now you can see the producer sends messages and the consumer receives messages successfully.
-
-   **Output**
-
-   This is from the producer side.
-
-   ```
-   Sent message: my-message-0
-   Sent message: my-message-1
-   Sent message: my-message-2
-   Sent message: my-message-3
-   Sent message: my-message-4
-   Sent message: my-message-5
-   Sent message: my-message-6
-   Sent message: my-message-7
-   Sent message: my-message-8
-   Sent message: my-message-9
-   ```
-
-   This is from the consumer side.
-
-   ```
-   my-message-0
-   my-message-1
-   my-message-2
-   my-message-3
-   my-message-4
-   my-message-5
-   my-message-6
-   my-message-7
-   my-message-8
-   my-message-9
-   ```
-
+Pulsar encryption allows applications to encrypt messages at producers and decrypt messages at consumers. See [cookbook](cookbooks-encryption.md) for more details.
diff --git a/site2/website-next/docs/client-libraries-python.md b/site2/website-next/docs/client-libraries-python.md
index 026afa093b8..8e4358fee83 100644
--- a/site2/website-next/docs/client-libraries-python.md
+++ b/site2/website-next/docs/client-libraries-python.md
@@ -515,100 +515,4 @@ consumer = client.subscribe(
 
 ## End-to-end encryption
 
-[End-to-end encryption](/cookbooks-encryption.md#docsNav) allows applications to encrypt messages at producers and decrypt messages at consumers.
-
-### Configuration
-
-To use the end-to-end encryption feature in the Python client, you need to configure `publicKeyPath` for producers and `privateKeyPath` for consumers.
-
-```
-publicKeyPath: "./public.pem"
-privateKeyPath: "./private.pem"
-```
-
-### Tutorial
-
-This section provides step-by-step instructions on how to use the end-to-end encryption feature in the Python client.
-
-**Prerequisite**
-
-- Pulsar Python client 2.7.1 or later
-
-**Step**
-
-1. Create both public and private key pairs.
-
-   **Input**
-
-   ```shell
-   openssl genrsa -out private.pem 2048
-   openssl rsa -in private.pem -pubout -out public.pem
-   ```
-
-2. Create a producer to send encrypted messages.
-
-   **Input**
-
-   ```python
-   import pulsar
-
-   publicKeyPath = "./public.pem"
-   privateKeyPath = ""
-   crypto_key_reader = pulsar.CryptoKeyReader(publicKeyPath, privateKeyPath)
-   client = pulsar.Client('pulsar://localhost:6650')
-   producer = client.create_producer(topic='encryption', encryption_key='encryption', crypto_key_reader=crypto_key_reader)
-   producer.send('encryption message'.encode('utf8'))
-   print('sent message')
-   producer.close()
-   client.close()
-   ```
-
-3. Create a consumer to receive encrypted messages.
-
-   **Input**
-
-   ```python
-   import pulsar
-
-   publicKeyPath = ""
-   privateKeyPath = "./private.pem"
-   crypto_key_reader = pulsar.CryptoKeyReader(publicKeyPath, privateKeyPath)
-   client = pulsar.Client('pulsar://localhost:6650')
-   consumer = client.subscribe(topic='encryption', subscription_name='encryption-sub', crypto_key_reader=crypto_key_reader)
-   msg = consumer.receive()
-   print("Received msg '{}' id = '{}'".format(msg.data(), msg.message_id()))
-   consumer.close()
-   client.close()
-   ```
-
-4. Run the consumer to receive encrypted messages.
-
-   **Input**
-
-   ```shell
-   python consumer.py
-   ```
-
-5. In a new terminal tab, run the producer to produce encrypted messages.
-
-   **Input**
-
-   ```shell
-   python producer.py
-   ```
-
-   Now you can see the producer sends messages and the consumer receives messages successfully.
-
-   **Output**
-
-   This is from the producer side.
-
-   ```
-   sent message
-   ```
-
-   This is from the consumer side.
-
-   ```
-   Received msg 'encryption message' id = '(0,0,-1,-1)'
-   ```
+Pulsar encryption allows applications to encrypt messages at producers and decrypt messages at consumers. See [cookbook](cookbooks-encryption.md) for more details.
\ No newline at end of file
diff --git a/site2/website-next/docs/cookbooks-encryption.md b/site2/website-next/docs/cookbooks-encryption.md
index 201b5986bcb..9aa321e73c0 100644
--- a/site2/website-next/docs/cookbooks-encryption.md
+++ b/site2/website-next/docs/cookbooks-encryption.md
@@ -1,46 +1,230 @@
 ---
 id: cookbooks-encryption
-title: Pulsar Encryption
-sidebar_label: "Encryption "
+title: Configure end-to-end encryption
+sidebar_label: "Configure end-to-end encryption"
 ---
 
-Pulsar encryption allows applications to encrypt messages at the producer and decrypt at the consumer. Encryption is performed using the public/private key pair configured by the application. Encrypted messages can only be decrypted by consumers with a valid key.
-
-## Asymmetric and symmetric encryption
-
-Pulsar uses a dynamically generated symmetric AES key to encrypt messages(data). The AES key(data key) is encrypted using the application-provided ECDSA/RSA key pair. As a result, there is no need to share the secret with everyone.
-
-Key is a public/private key pair used for encryption/decryption. The producer key is the public key, and the consumer key is the private key of the key pair.
-
-The application configures the producer with the public key. This key is used to encrypt the AES data key. The encrypted data key is sent as part of the message header. Only entities with the private key(in this case the consumer) will be able to decrypt the data key which is used to decrypt the message.
-
-A message can be encrypted with more than one key.  Any one of the keys used for encrypting the message is sufficient to decrypt the message
-
-Pulsar does not store the encryption key anywhere in the pulsar service. If you lose/delete the private key, your message is irretrievably lost, and is unrecoverable
-
-## Producer
-![alt text](/assets/pulsar-encryption-producer.jpg "Pulsar Encryption Producer")
-
-## Consumer
-![alt text](/assets/pulsar-encryption-consumer.jpg "Pulsar Encryption Consumer")
-
-## Here are the steps to get started:
-
-1. Create your ECDSA or RSA public/private key pair.
-
-```shell
-openssl ecparam -name secp521r1 -genkey -param_enc explicit -out test_ecdsa_privkey.pem
-openssl ec -in test_ecdsa_privkey.pem -pubout -outform pkcs8 -out test_ecdsa_pubkey.pem
-```
-
-2. Add the public and private key to the key management and configure your producers to retrieve public keys and consumers clients to retrieve private keys.
-3. Implement CryptoKeyReader::getPublicKey() interface from producer and CryptoKeyReader::getPrivateKey() interface from consumer, which will be invoked by Pulsar client to load the key.
-4. Add encryption key to producer configuration: conf.addEncryptionKey("myapp.key")
-5. Add CryptoKeyReader implementation to producer/consumer config: conf.setCryptoKeyReader(keyReader)
-6. Sample producer application:
-
-```java
-class RawFileKeyReader implements CryptoKeyReader {
+````mdx-code-block
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+````
+
+[Pulsar encryption](security-encryption.md) allows clients to encrypt messages at producers and decrypt messages at consumers.
+
+## Prerequisites
+
+* Pulsar Java/Python/C++/Node.js client 2.7.1 or later versions.
+* Pulsar Go client 0.6.0 or later versions.
+
+## Configure end-to-end encryption
+
+1. Create both public and private key pairs.
+   * ECDSA(for Java and Go clients)
+     ```shell
+     openssl ecparam -name secp521r1 -genkey -param_enc explicit -out test_ecdsa_privkey.pem
+     openssl ec -in test_ecdsa_privkey.pem -pubout -outform pem -out test_ecdsa_pubkey.pem
+     ```
+
+   * RSA (for Python, C++ and Node.js clients)
+     ```shell
+     openssl genrsa -out test_rsa_privkey.pem 2048
+     openssl rsa -in test_rsa_privkey.pem -pubout -outform pkcs8 -out test_rsa_pubkey.pem
+     ```
+
+2. Configure a `CryptoKeyReader` on producers, consumers or readers.
+
+   ````mdx-code-block
+   <Tabs groupId="lang-choice"
+     defaultValue="Java"
+     values={[{"label":"Java","value":"Java"},{"label":"Python","value":"Python"},{"label":"C++","value":"C++"},{"label":"Go","value":"Go"},{"label":"Node.js","value":"Node.js"}]}>
+   <TabItem value="Java">
+
+   ```java
+   PulsarClient pulsarClient = PulsarClient.builder().serviceUrl("pulsar://localhost:6650").build();
+   String topic = "persistent://my-tenant/my-ns/my-topic";
+   // RawFileKeyReader is just an example implementation that's not provided by Pulsar
+   CryptoKeyReader keyReader = new RawFileKeyReader("test_ecdsa_pubkey.pem", "test_ecdsa_privkey.pem");
+
+   Producer<byte[]> producer = pulsarClient.newProducer()
+        .topic(topic)
+        .cryptoKeyReader(keyReader)
+        .addEncryptionKey("myappkey")
+        .create();
+
+   Consumer<byte[]> consumer = pulsarClient.newConsumer()
+        .topic(topic)
+        .subscriptionName("my-subscriber-name")
+        .cryptoKeyReader(keyReader)
+        .subscribe();
+
+   Reader<byte[]> reader = pulsarClient.newReader()
+        .topic(topic)
+        .startMessageId(MessageId.earliest)
+        .cryptoKeyReader(keyReader)
+        .create();
+   ```
+
+   </TabItem>
+   <TabItem value="Python">
+
+   ```python
+   from pulsar import Client, CryptoKeyReader
+
+   client = Client('pulsar://localhost:6650')
+   topic = 'my-topic'
+   # CryptoKeyReader is a built-in implementation that reads public key and private key from files
+   key_reader = CryptoKeyReader('test_rsa_pubkey.pem', 'test_rsa_privkey.pem')
+
+   producer = client.create_producer(
+       topic=topic,
+       encryption_key='myappkey',
+       crypto_key_reader=key_reader
+   )
+
+   consumer = client.subscribe(
+       topic=topic,
+       subscription_name='my-subscriber-name',
+       crypto_key_reader=key_reader
+   )
+
+   reader = client.create_reader(
+       topic=topic,
+       start_message_id=MessageId.earliest,
+       crypto_key_reader=key_reader
+   )
+
+   client.close()
+   ```
+
+   </TabItem>
+   <TabItem value="C++">
+
+   ```cpp
+   Client client("pulsar://localhost:6650");
+   std::string topic = "persistent://my-tenant/my-ns/my-topic";
+   // DefaultCryptoKeyReader is a built-in implementation that reads public key and private key from files
+   auto keyReader = std::make_shared<DefaultCryptoKeyReader>("test_rsa_pubkey.pem", "test_rsa_privkey.pem");
+
+   Producer producer;
+   ProducerConfiguration producerConf;
+   producerConf.setCryptoKeyReader(keyReader);
+   producerConf.addEncryptionKey("myappkey");
+   client.createProducer(topic, producerConf, producer);
+
+   Consumer consumer;
+   ConsumerConfiguration consumerConf;
+   consumerConf.setCryptoKeyReader(keyReader);
+   client.subscribe(topic, "my-subscriber-name", consumerConf, consumer);
+
+   Reader reader;
+   ReaderConfiguration readerConf;
+   readerConf.setCryptoKeyReader(keyReader);
+   client.createReader(topic, MessageId::earliest(), readerConf, reader);
+   ```
+
+   </TabItem>
+   <TabItem value="Go">
+
+   ```go
+   client, err := pulsar.NewClient(pulsar.ClientOptions{
+	 URL: "pulsar://localhost:6650",
+   })
+   if err != nil {
+	   log.Fatal(err)
+   }
+
+   defer client.Close()
+
+   topic := "persistent://my-tenant/my-ns/my-topic"
+   keyReader := crypto.NewFileKeyReader("test_ecdsa_pubkey.pem", "test_ecdsa_privkey.pem")
+   producer, err := client.CreateProducer(pulsar.ProducerOptions{
+	   Topic: topic,
+	   Encryption: &pulsar.ProducerEncryptionInfo{
+	   	KeyReader: keyReader,
+	   	Keys:      []string{"myappkey"},
+	   },
+   })
+   if err != nil {
+   	log.Fatal(err)
+   }
+   defer producer.Close()
+
+   consumer, err := client.Subscribe(pulsar.ConsumerOptions{
+	   Topic:            topic,
+	   SubscriptionName: "my-subscriber-name",
+	   Decryption: &pulsar.MessageDecryptionInfo{
+		   KeyReader: keyReader,
+	   },
+   })
+   if err != nil {
+	   log.Fatal(err)
+   }
+   defer consumer.Close()
+
+   reader, err := client.CreateReader(pulsar.ReaderOptions{
+	   Topic: topic,
+	   Decryption: &pulsar.MessageDecryptionInfo{
+		   KeyReader: keyReader,
+	   },
+   })
+   if err != nil {
+	   log.Fatal(err)
+   }
+   defer reader.Close()
+   ```
+
+   </TabItem>
+   <TabItem value="Node.js">
+
+   ```javascript
+   const Pulsar = require('pulsar-client');
+
+   const topic = 'persistent://my-tenant/my-ns/my-topic';
+
+   (async () => {
+   // Create a client
+   const client = new Pulsar.Client({
+       serviceUrl: 'pulsar://localhost:6650',
+       operationTimeoutSeconds: 30,
+   });
+
+   // Create a producer
+   const producer = await client.createProducer({
+       topic: topic,
+       sendTimeoutMs: 30000,
+       batchingEnabled: true,
+       publicKeyPath: "test_rsa_pubkey.pem",
+       encryptionKey: "encryption-key"
+   });
+
+   // Create a consumer
+   const consumer = await client.subscribe({
+       topic: topic,
+       subscription: 'my-subscriber-name',
+       subscriptionType: 'Shared',
+       ackTimeoutMs: 10000,
+       privateKeyPath: "test_rsa_privkey.pem"
+   });
+   await consumer.close();
+   await producer.close();
+   await client.close();
+   })();
+   ```
+
+   </TabItem>
+   </Tabs>
+   ````
+
+3. Optional: customize the `CryptoKeyReader` implementation.
+   
+   ````mdx-code-block
+   <Tabs groupId="lang-choice"
+     defaultValue="Java"
+     values={[{"label":"Java","value":"Java"},{"label":"Python","value":"Python"},{"label":"C++","value":"C++"},{"label":"Go","value":"Go"},{"label":"Node.js","value":"Node.js"}]}>
+   <TabItem value="Java">
+
+   ```java
+   class RawFileKeyReader implements CryptoKeyReader {
 
     String publicKeyFile = "";
     String privateKeyFile = "";
@@ -73,104 +257,78 @@ class RawFileKeyReader implements CryptoKeyReader {
         }
         return keyInfo;
     }
-}
-PulsarClient pulsarClient = PulsarClient.create("http://localhost:8080");
-
-ProducerConfiguration prodConf = new ProducerConfiguration();
-prodConf.setCryptoKeyReader(new RawFileKeyReader("test_ecdsa_pubkey.pem", "test_ecdsa_privkey.pem"));
-prodConf.addEncryptionKey("myappkey");
-
-Producer producer = pulsarClient.createProducer("persistent://my-tenant/my-ns/my-topic", prodConf);
-
-for (int i = 0; i < 10; i++) {
-    producer.send("my-message".getBytes());
-}
-
-pulsarClient.close();
-```
+   }
+   ```
 
-7. Sample Consumer Application:
+   </TabItem>
+   <TabItem value="Python">
 
-```java
-class RawFileKeyReader implements CryptoKeyReader {
+   Currently, customizing the `CryptoKeyReader` implementation is not supported in Python. However, you can use the default implementation by specifying the path of the private key and public keys.
 
-    String publicKeyFile = "";
-    String privateKeyFile = "";
+   </TabItem>
+   <TabItem value="C++">
 
-    RawFileKeyReader(String pubKeyFile, String privKeyFile) {
-        publicKeyFile = pubKeyFile;
-        privateKeyFile = privKeyFile;
+   ```cpp
+   class CustomCryptoKeyReader : public CryptoKeyReader {
+    public:
+    Result getPublicKey(const std::string& keyName, std::map<std::string, std::string>& metadata,
+                        EncryptionKeyInfo& encKeyInfo) const override {
+        // TODO
+        return ResultOk;
     }
 
-    @Override
-    public EncryptionKeyInfo getPublicKey(String keyName, Map<String, String> keyMeta) {
-        EncryptionKeyInfo keyInfo = new EncryptionKeyInfo();
-        try {
-            keyInfo.setKey(Files.readAllBytes(Paths.get(publicKeyFile)));
-        } catch (IOException e) {
-            System.out.println("ERROR: Failed to read public key from file " + publicKeyFile);
-            e.printStackTrace();
-        }
-        return keyInfo;
+    Result getPrivateKey(const std::string& keyName, std::map<std::string, std::string>& metadata,
+                        EncryptionKeyInfo& encKeyInfo) const override {
+        // TODO
+        return ResultOk;
     }
+   };
+   ```
 
-    @Override
-    public EncryptionKeyInfo getPrivateKey(String keyName, Map<String, String> keyMeta) {
-        EncryptionKeyInfo keyInfo = new EncryptionKeyInfo();
-        try {
-            keyInfo.setKey(Files.readAllBytes(Paths.get(privateKeyFile)));
-        } catch (IOException e) {
-            System.out.println("ERROR: Failed to read private key from file " + privateKeyFile);
-            e.printStackTrace();
-        }
-        return keyInfo;
-    }
-}
+   </TabItem>
+   <TabItem value="Go">
 
-ConsumerConfiguration consConf = new ConsumerConfiguration();
-consConf.setCryptoKeyReader(new RawFileKeyReader("test_ecdsa_pubkey.pem", "test_ecdsa_privkey.pem"));
-PulsarClient pulsarClient = PulsarClient.create("http://localhost:8080");
-Consumer consumer = pulsarClient.subscribe("persistent://my-tenant//my-ns/my-topic", "my-subscriber-name", consConf);
-Message msg = null;
+   ```go
+   type CustomKeyReader struct {
+	   publicKeyPath  string
+	   privateKeyPath string
+   }
 
-for (int i = 0; i < 10; i++) {
-    msg = consumer.receive();
-    // do something
-    System.out.println("Received: " + new String(msg.getData()));
-}
+   func (c *CustomKeyReader) PublicKey(keyName string, keyMeta map[string]string) (*EncryptionKeyInfo, error) {
+	   keyInfo := &EncryptionKeyInfo{}
+	   // TODO
+	   return keyInfo, nil
+   }
 
-// Acknowledge the consumption of all messages at once
-consumer.acknowledgeCumulative(msg);
-pulsarClient.close();
-```
+   // PrivateKey read private key from the given path
+   func (c *CustomKeyReader) PrivateKey(keyName string, keyMeta map[string]string) (*EncryptionKeyInfo, error) {
+	   keyInfo := &EncryptionKeyInfo{}
+	   // TODO
+	   return keyInfo, nil
+   }
+   ```
 
-## Key rotation
-Pulsar generates a new AES data key every 4 hours or after a certain number of messages are published. The asymmetric public key is automatically fetched by producers every 4 hours by calling CryptoKeyReader::getPublicKey() to retrieve the latest version.
+   </TabItem>
+   <TabItem value="Node.js">
 
-## Enabling encryption at the producer application:
-If you produce messages that are consumed across application boundaries, you need to ensure that consumers in other applications have access to one of the private keys that can decrypt the messages.  This can be done in two ways:
-1. The consumer application provides you access to their public key, which you add to your producer keys
-1. You grant access to one of the private keys from the pairs used by producers
+   Currently, customizing the `CryptoKeyReader` implementation is not supported in Python. However, you can use the default implementation by specifying the path of the private key and public keys.
 
-In some cases, the producer may want to encrypt the messages with multiple keys. For this, add all such keys to the config. Consumers will be able to decrypt the message, as long as it has access to at least one of the keys.
+   </TabItem>
+   </Tabs>
+   ````
 
-For example, to encrypt messages using 2 keys `myapp.messagekey1` and `myapp.messagekey2`, do the following:
+## Encrypt a message with multiple keys
 
-```java
+:::note
 
-conf.addEncryptionKey("myapp.messagekey1");
-conf.addEncryptionKey("myapp.messagekey2");
+This is only available for Java clients.
 
-```
+:::
 
-## Decrypting encrypted messages at the consumer application:
-Consumers require to access one of the private keys to decrypt messages produced by the producer. If you would like to receive encrypted messages, create a public/private key and give your public key to the producer application to encrypt messages using your public key.
+You can encrypt a message with more than one key. Producers add all such keys to the config and consumers can decrypt the message as long as they have access to at least one of the keys. Any one of the keys used for encrypting the message is sufficient to decrypt the message. 
 
-## Handling Failures:
-* Producer/ Consumer loses access to the key
-  * Producer action will fail to indicate the cause of the failure. The application has the option to proceed with sending unencrypted messages in such cases. Call `conf.setCryptoFailureAction`(ProducerCryptoFailureAction) to control the producer behavior. The default behavior is to fail the request.
-  * If consumption failed due to decryption failure or missing keys in consumers, the application has the option to consume the encrypted message or discard it. Call conf.setCryptoFailureAction(ConsumerCryptoFailureAction) to control the consumer behavior. The default behavior is to fail the request. The application will never be able to decrypt the messages if the private key is permanently lost.
-* Batch messaging
-  * If decryption fails and the message contains batch messages, the client will not be able to retrieve individual messages in the batch, hence message consumption fails even if conf.setCryptoFailureAction() is set to CONSUME.
-* If decryption fails, the message consumption stops and the application will notice backlog growth in addition to decryption failure messages in the client log. If the application does not have access to the private key to decrypt the message, the only option is to skip/discard backlogged messages. 
+For example, encrypt the messages using 2 keys (`myapp.messagekey1` and `myapp.messagekey2`):
 
+```java
+PulsarClient.newProducer().addEncryptionKey("myapp.messagekey1").addEncryptionKey("myapp.messagekey2");
+```
\ No newline at end of file
diff --git a/site2/website-next/docs/io-connectors.md b/site2/website-next/docs/io-connectors.md
index 83986c8c827..1b6f9e85bc2 100644
--- a/site2/website-next/docs/io-connectors.md
+++ b/site2/website-next/docs/io-connectors.md
@@ -101,7 +101,13 @@ Pulsar has various source connectors, which are sorted alphabetically as below.
 * [Configuration](io-kinesis-source.md#configuration)
   
 * [Java class](https://github.com/apache/pulsar/blob/master/pulsar-io/kinesis/src/main/java/org/apache/pulsar/io/kinesis/KinesisSource.java)
-  
+
+### MongoDB
+
+* [Configuration](io-mongo-source.md#configuration)
+
+* [Java class](https://github.com/apache/pulsar/blob/master/pulsar-io/mongo/src/main/java/org/apache/pulsar/io/mongodb/MongoSource.java)
+
 ### Netty
 
 * [Configuration](io-netty-source.md#configuration)
diff --git a/site2/website-next/docs/io-mongo-source.md b/site2/website-next/docs/io-mongo-source.md
new file mode 100644
index 00000000000..a525cb79b32
--- /dev/null
+++ b/site2/website-next/docs/io-mongo-source.md
@@ -0,0 +1,55 @@
+---
+id: io-mongo-source
+title: MongoDB source connector
+sidebar_label: "MongoDB source connector"
+---
+
+The MongoDB source connector pulls documents from MongoDB and persists the messages to Pulsar topics.
+
+This guide explains how to configure and use the MongoDB source connector.
+
+## Configuration
+
+The configuration of the MongoDB source connector has the following properties.
+
+### Property
+
+| Name          | Type   | Required | Default            | Description                                                                                                                                                                                    |
+|---------------|--------|----------|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `mongoUri`    | String | true     | " " (empty string) | The MongoDB URI to which the connector connects. <br /><br />For more information, see [connection string URI format](https://docs.mongodb.com/manual/reference/connection-string/).           |
+| `database`    | String | false    | " " (empty string) | The name of the watched database. <br /><br />If this field is not set, the source connector will watch the entire MongoDB for all changes.                                                    |
+| `collection`  | String | false    | " " (empty string) | The name of the watched collection. <br /><br />If this field is not set, the source connector will watch the database for all changes.                                                        |
+| `syncType`    | String | false    | "INCR_SYNC"        | The synchronization type between MongoDB and Pulsar: full synchronization or incremental synchronization. <br /><br /> Valid values are `full_sync`, `FULL_SYNC`, `incr_sync` and `INCR_SYNC`. |
+| `batchSize`   | int    | false    | 100                | The batch size of pulling documents from collections.                                                                                                                                          |
+| `batchTimeMs` | long   | false    | 1000               | The batch operation interval in milliseconds.                                                                                                                                                  |
+
+### Example
+
+Before using the Mongo source connector, you need to create a configuration file through one of the following methods.
+
+* JSON
+
+  ```json
+  {
+     "configs": {
+        "mongoUri": "mongodb://localhost:27017",
+        "database": "pulsar",
+        "collection": "messages",
+        "syncType": "full_sync",
+        "batchSize": "2",
+        "batchTimeMs": "500"
+     }
+  }
+  ```
+
+* YAML
+
+  ```yaml
+  configs:
+      mongoUri: "mongodb://localhost:27017"
+      database: "pulsar"
+      collection: "messages"
+      syncType: "full_sync",
+      batchSize: 2
+      batchTimeMs: 500
+  ```
diff --git a/site2/website-next/docs/security-authorization.md b/site2/website-next/docs/security-authorization.md
index 046e3361b82..2b0d9016c62 100644
--- a/site2/website-next/docs/security-authorization.md
+++ b/site2/website-next/docs/security-authorization.md
@@ -5,7 +5,7 @@ sidebar_label: "Authorization and ACLs"
 ---
 
 
-In Pulsar, the [authentication provider](security-overview.md#authentication-providers) is responsible for properly identifying clients and associating the clients with [role tokens](security-overview.md#role-tokens). If you only enable authentication, an authenticated role token can access all resources in the cluster. *Authorization* is the process that determines _what_ clients can do.
+In Pulsar, the [authentication provider](security-overview.md#authentication) is responsible for properly identifying clients and associating the clients with role tokens. If you only enable authentication, an authenticated role token can access all resources in the cluster. *Authorization* is the process that determines _what_ clients can do.
 
 The role tokens with the most privileges are the *superusers*. The *superusers* can create and destroy tenants, along with having full access to all tenant resources.
 
diff --git a/site2/website-next/docs/security-encryption.md b/site2/website-next/docs/security-encryption.md
index f57b312baa7..af21e5a33bd 100644
--- a/site2/website-next/docs/security-encryption.md
+++ b/site2/website-next/docs/security-encryption.md
@@ -9,308 +9,40 @@ import Tabs from '@theme/Tabs';
 import TabItem from '@theme/TabItem';
 ````
 
+Applications can use Pulsar end-to-end encryption (E2EE) to encrypt messages on the producer side and decrypt messages on the consumer side. You can use the public and private key pair that the application configures to perform encryption and decryption. Only the consumers with a valid key can decrypt the encrypted messages.
 
-Applications can use Pulsar encryption to encrypt messages on the producer side and decrypt messages on the consumer side. You can use the public and private key pair that the application configures to perform encryption. Only the consumers with a valid key can decrypt the encrypted messages.
+## How it works
 
-## Asymmetric and symmetric encryption
+Pulsar uses a dynamically generated symmetric AES key to encrypt messages (data). You can use the application-provided ECDSA (Elliptic Curve Digital Signature Algorithm) or RSA (Rivest–Shamir–Adleman) key pair to encrypt the AES key (data key), so you do not have to share the secret with everyone.
 
-Pulsar uses a dynamically generated symmetric AES key to encrypt messages(data). You can use the application-provided ECDSA (Elliptic Curve Digital Signature Algorithm) or RSA (Rivest–Shamir–Adleman) key pair to encrypt the AES key(data key), so you do not have to share the secret with everyone.
+The application configures the producer with the public key for encryption. You can use this key to encrypt the AES data key. The encrypted data key is sent as part of the message header. Only entities with the private key (in this case the consumer) can decrypt the data key which is used to decrypt the message.
 
-Key is a public and private key pair used for encryption or decryption. The producer key is the public key of the key pair, and the consumer key is the private key of the key pair.
+The following figure illustrates how Pulsar encrypts messages on the producer side and decrypts messages on the consumer side.
 
-The application configures the producer with the public key. You can use this key to encrypt the AES data key. The encrypted data key is sent as part of the message header. Only entities with the private key (in this case the consumer) can decrypt the data key which is used to decrypt the message.
+![alt text](/assets/pulsar-encryption.svg "Pulsar Encryption Process")
 
-You can encrypt a message with more than one key. Any one of the keys used for encrypting the message is sufficient to decrypt the message.
-
-Pulsar does not store the encryption key anywhere in the Pulsar service. If you lose or delete the private key, your message is irretrievably lost and unrecoverable.
-
-## Producer
-![alt text](/assets/pulsar-encryption-producer.jpg "Pulsar Encryption Producer")
-
-## Consumer
-![alt text](/assets/pulsar-encryption-consumer.jpg "Pulsar Encryption Consumer")
-
-## Get started
-
-1. Create your ECDSA or RSA public and private key pair by using the following commands.
-  * ECDSA(for Java clients only)
-
-   ```shell
-   openssl ecparam -name secp521r1 -genkey -param_enc explicit -out test_ecdsa_privkey.pem
-   openssl ec -in test_ecdsa_privkey.pem -pubout -outform pem -out test_ecdsa_pubkey.pem
-   ```
-
-  * RSA (for C++, Python and Node.js clients)
-
-   ```shell
-   openssl genrsa -out test_rsa_privkey.pem 2048
-   openssl rsa -in test_rsa_privkey.pem -pubout -outform pkcs8 -out test_rsa_pubkey.pem
-   ```
-
-2. Add the public and private keys to the key management and configure your producers to retrieve public keys and consumer clients to retrieve private keys.
-
-3. Implement the `CryptoKeyReader` interface, specifically `CryptoKeyReader.getPublicKey()` for producer and `CryptoKeyReader.getPrivateKey()` for consumer, which Pulsar client invokes to load the key.
-
-4. Add the encryption key name to the producer builder: PulsarClient.newProducer().addEncryptionKey("myapp.key").
-
-5. Configure a `CryptoKeyReader` to a producer, consumer or reader.
-
-````mdx-code-block
-<Tabs groupId="lang-choice"
-  defaultValue="Java"
-  values={[{"label":"Java","value":"Java"},{"label":"C++","value":"C++"},{"label":"Python","value":"Python"},{"label":"Node.js","value":"Node.js"}]}>
-<TabItem value="Java">
-
-```java
-PulsarClient pulsarClient = PulsarClient.builder().serviceUrl("pulsar://localhost:6650").build();
-String topic = "persistent://my-tenant/my-ns/my-topic";
-// RawFileKeyReader is just an example implementation that's not provided by Pulsar
-CryptoKeyReader keyReader = new RawFileKeyReader("test_ecdsa_pubkey.pem", "test_ecdsa_privkey.pem");
-
-Producer<byte[]> producer = pulsarClient.newProducer()
-        .topic(topic)
-        .cryptoKeyReader(keyReader)
-        .addEncryptionKey("myappkey")
-        .create();
-
-Consumer<byte[]> consumer = pulsarClient.newConsumer()
-        .topic(topic)
-        .subscriptionName("my-subscriber-name")
-        .cryptoKeyReader(keyReader)
-        .subscribe();
-
-Reader<byte[]> reader = pulsarClient.newReader()
-        .topic(topic)
-        .startMessageId(MessageId.earliest)
-        .cryptoKeyReader(keyReader)
-        .create();
-```
-
-</TabItem>
-<TabItem value="C++">
-
-```cpp
-Client client("pulsar://localhost:6650");
-std::string topic = "persistent://my-tenant/my-ns/my-topic";
-// DefaultCryptoKeyReader is a built-in implementation that reads public key and private key from files
-auto keyReader = std::make_shared<DefaultCryptoKeyReader>("test_rsa_pubkey.pem", "test_rsa_privkey.pem");
-
-Producer producer;
-ProducerConfiguration producerConf;
-producerConf.setCryptoKeyReader(keyReader);
-producerConf.addEncryptionKey("myappkey");
-client.createProducer(topic, producerConf, producer);
-
-Consumer consumer;
-ConsumerConfiguration consumerConf;
-consumerConf.setCryptoKeyReader(keyReader);
-client.subscribe(topic, "my-subscriber-name", consumerConf, consumer);
-
-Reader reader;
-ReaderConfiguration readerConf;
-readerConf.setCryptoKeyReader(keyReader);
-client.createReader(topic, MessageId::earliest(), readerConf, reader);
-```
-
-</TabItem>
-<TabItem value="Python">
-
-```python
-from pulsar import Client, CryptoKeyReader
-
-client = Client('pulsar://localhost:6650')
-topic = 'persistent://my-tenant/my-ns/my-topic'
-# CryptoKeyReader is a built-in implementation that reads public key and private key from files
-key_reader = CryptoKeyReader('test_rsa_pubkey.pem', 'test_rsa_privkey.pem')
-
-producer = client.create_producer(
-    topic=topic,
-    encryption_key='myappkey',
-    crypto_key_reader=key_reader
-)
-
-consumer = client.subscribe(
-    topic=topic,
-    subscription_name='my-subscriber-name',
-    crypto_key_reader=key_reader
-)
-
-reader = client.create_reader(
-    topic=topic,
-    start_message_id=MessageId.earliest,
-    crypto_key_reader=key_reader
-)
-
-client.close()
-```
-
-</TabItem>
-<TabItem value="Node.js">
-
-```javascript
-const Pulsar = require('pulsar-client');
-
-(async () => {
-// Create a client
-const client = new Pulsar.Client({
-    serviceUrl: 'pulsar://localhost:6650',
-    operationTimeoutSeconds: 30,
-});
-
-// Create a producer
-const producer = await client.createProducer({
-    topic: 'persistent://public/default/my-topic',
-    sendTimeoutMs: 30000,
-    batchingEnabled: true,
-    publicKeyPath: "public-key.client-rsa.pem",
-    encryptionKey: "encryption-key"
-});
-
-// Create a consumer
-const consumer = await client.subscribe({
-    topic: 'persistent://public/default/my-topic',
-    subscription: 'sub1',
-    subscriptionType: 'Shared',
-    ackTimeoutMs: 10000,
-    privateKeyPath: "private-key.client-rsa.pem"
-});
-
-// Send messages
-for (let i = 0; i < 10; i += 1) {
-    const msg = `my-message-${i}`;
-    producer.send({
-    data: Buffer.from(msg),
-    });
-    console.log(`Sent message: ${msg}`);
-}
-await producer.flush();
-
-// Receive messages
-for (let i = 0; i < 10; i += 1) {
-    const msg = await consumer.receive();
-    console.log(msg.getData().toString());
-    consumer.acknowledge(msg);
-}
-
-await consumer.close();
-await producer.close();
-await client.close();
-})();
-```
-
-</TabItem>
-
-</Tabs>
-````
-
-6. Below is an example of a **customized** `CryptoKeyReader` implementation.
-
-````mdx-code-block
-<Tabs groupId="lang-choice"
-  defaultValue="Java"
-  values={[{"label":"Java","value":"Java"},{"label":"C++","value":"C++"},{"label":"Python","value":"Python"},{"label":"Node.js","value":"Node.js"}]}>
-<TabItem value="Java">
-
-```java
-class RawFileKeyReader implements CryptoKeyReader {
-
-    String publicKeyFile = "";
-    String privateKeyFile = "";
-
-    RawFileKeyReader(String pubKeyFile, String privKeyFile) {
-        publicKeyFile = pubKeyFile;
-        privateKeyFile = privKeyFile;
-    }
-
-    @Override
-    public EncryptionKeyInfo getPublicKey(String keyName, Map<String, String> keyMeta) {
-        EncryptionKeyInfo keyInfo = new EncryptionKeyInfo();
-        try {
-            keyInfo.setKey(Files.readAllBytes(Paths.get(publicKeyFile)));
-        } catch (IOException e) {
-            System.out.println("ERROR: Failed to read public key from file " + publicKeyFile);
-            e.printStackTrace();
-        }
-        return keyInfo;
-    }
-
-    @Override
-    public EncryptionKeyInfo getPrivateKey(String keyName, Map<String, String> keyMeta) {
-        EncryptionKeyInfo keyInfo = new EncryptionKeyInfo();
-        try {
-            keyInfo.setKey(Files.readAllBytes(Paths.get(privateKeyFile)));
-        } catch (IOException e) {
-            System.out.println("ERROR: Failed to read private key from file " + privateKeyFile);
-            e.printStackTrace();
-        }
-        return keyInfo;
-    }
-}
-```
-
-</TabItem>
-<TabItem value="C++">
-
-```cpp
-class CustomCryptoKeyReader : public CryptoKeyReader {
-    public:
-    Result getPublicKey(const std::string& keyName, std::map<std::string, std::string>& metadata,
-                        EncryptionKeyInfo& encKeyInfo) const override {
-        // TODO:
-        return ResultOk;
-    }
-
-    Result getPrivateKey(const std::string& keyName, std::map<std::string, std::string>& metadata,
-                        EncryptionKeyInfo& encKeyInfo) const override {
-        // TODO:
-        return ResultOk;
-    }
-};
-
-auto keyReader = std::make_shared<CustomCryptoKeyReader>(/* ... */);
-// TODO: create producer, consumer or reader based on keyReader here
-```
-
-Besides, you can use the **default** implementation of `CryptoKeyReader` by specifying the paths of `private key` and `public key`.
-
-</TabItem>
-<TabItem value="Python">
-
-Currently, **customized** `CryptoKeyReader` implementation is not supported in Python. However, you can use the **default** implementation by specifying the path of `private key` and `public key`.
-
-</TabItem>
-<TabItem value="Node.js">
+If produced messages are consumed across application boundaries, you need to ensure that consumers in other applications have access to one of the private keys that can decrypt the messages. You can do this in two ways:
+1. The consumer application provides you access to the public key, which you add to your producer keys.
+2. You grant access to one of the private keys from the pairs that the producer uses. 
 
-Currently, **customized** `CryptoKeyReader` implementation is not supported in Node.js. However, you can use the **default** implementation by specifying the path of `private key` and `public key`.
+:::tip
 
-</TabItem>
+* Pulsar does not store the encryption key anywhere in the Pulsar service. If you lose or delete the private key, your message is irretrievably lost and unrecoverable.
+* Pulsar generates a new AES data key every 4 hours or after publishing a certain number of messages. Producers fetch the asymmetric public key every 4 hours by calling `CryptoKeyReader.getPublicKey()` to retrieve the latest version.
 
-</Tabs>
-````
+:::
 
-## Key rotation
-Pulsar generates a new AES data key every 4 hours or after publishing a certain number of messages. A producer fetches the asymmetric public key every 4 hours by calling `CryptoKeyReader.getPublicKey()` to retrieve the latest version.
 
-## Enable encryption at the producer application
-If you produce messages that are consumed across application boundaries, you need to ensure that consumers in other applications have access to one of the private keys that can decrypt the messages. You can do this in two ways:
-1. The consumer application provides you access to their public key, which you add to your producer keys.
-2. You grant access to one of the private keys from the pairs that the producer uses. 
-
-When producers want to encrypt the messages with multiple keys, producers add all such keys to the config. Consumers can decrypt the message as long as they have access to at least one of the keys.
+## Get started
 
-If you need to encrypt the messages using 2 keys (`myapp.messagekey1` and `myapp.messagekey2`), refer to the following example.
+Pulsar encryption allows applications to encrypt messages on the producer side and decrypt messages on the consumer side. See [cookbook](cookbooks-encryption.md) for detailed instructions.
 
-```java
-PulsarClient.newProducer().addEncryptionKey("myapp.messagekey1").addEncryptionKey("myapp.messagekey2");
-```
 
-## Decrypt encrypted messages at the consumer application
-Consumers require to access one of the private keys to decrypt messages that the producer produces. If you want to receive encrypted messages, create a public or private key and give your public key to the producer application to encrypt messages using your public key.
+## Troubleshoot
 
-## Handle failures
 * Producer/Consumer loses access to the key
   * Producer action fails to indicate the cause of the failure. Application has the option to proceed with sending unencrypted messages in such cases. Call `PulsarClient.newProducer().cryptoFailureAction(ProducerCryptoFailureAction)` to control the producer behavior. The default behavior is to fail the request.
   * If consumption fails due to decryption failure or missing keys in the consumer, the application has the option to consume the encrypted message or discard it. Call `PulsarClient.newConsumer().cryptoFailureAction(ConsumerCryptoFailureAction)` to control the consumer behavior. The default behavior is to fail the request. Application is never able to decrypt the messages if the private key is permanently lost.
 * Batch messaging
-  * If decryption fails and the message contains batch messages, client is not able to retrieve individual messages in the batch, hence message consumption fails even if cryptoFailureAction() is set to `ConsumerCryptoFailureAction.CONSUME`.
+  * If decryption fails and the message contains batch messages, client is not able to retrieve individual messages in the batch, hence message consumption fails even if `cryptoFailureAction()` is set to `ConsumerCryptoFailureAction.CONSUME`.
 * If decryption fails, the message consumption stops and the application notices backlog growth in addition to decryption failure messages in the client log. If the application does not have access to the private key to decrypt the message, the only option is to skip or discard backlogged messages.
diff --git a/site2/website-next/docs/security-overview.md b/site2/website-next/docs/security-overview.md
index 27b8521c5e9..658612df4c7 100644
--- a/site2/website-next/docs/security-overview.md
+++ b/site2/website-next/docs/security-overview.md
@@ -4,33 +4,53 @@ title: Pulsar security overview
 sidebar_label: "Overview"
 ---
 
-As the central message bus for a business, Apache Pulsar is frequently used for storing mission-critical data. Therefore, enabling security features in Pulsar is crucial.
+As the central message bus for a business, Apache Pulsar is frequently used for storing mission-critical data. Therefore, enabling security features in Pulsar is crucial. This chapter describes the main security controls that Pulsar uses to help protect your data.
 
-By default, Pulsar configures no encryption, authentication, or authorization. Any client can communicate to Apache Pulsar via plain text service URLs. So we must ensure that Pulsar accessing via these plain text service URLs is restricted to trusted clients only. In such cases, you can use Network segmentation and/or authorization ACLs to restrict access to trusted IPs. If you use neither, the state of the cluster is wide open and anyone can access the cluster.
+Pulsar security is based on the following core pillars.
+* [Encryption](#encryption)
+* [Authentication](#authentication)
+* [Authorization](#authorization)
 
-Pulsar supports a pluggable authentication mechanism. And Pulsar clients use this mechanism to authenticate with brokers and proxies. You can also configure Pulsar to support multiple authentication sources.
+By default, Pulsar configures no encryption, authentication, or authorization. Any clients can communicate to Pulsar via plain text service URLs. So you must ensure that Pulsar accessing via these plain text service URLs is restricted to trusted clients only. In such cases, you can use network segmentation and/or authorization ACLs to restrict access to trusted IPs. If you use neither, the state of the cluster is wide open and anyone can access the cluster.
 
-The Pulsar broker validates the authentication credentials when a connection is established. After the initial connection is authenticated, the "principal" token is stored for authorization though the connection is not re-authenticated. The broker periodically checks the expiration status of every `ServerCnx` object. You can set the `authenticationRefreshCheckSeconds` on the broker to control the frequency to check the expiration status. By default, the `authenticationRefreshCheckSeconds [...]
+Apache Pulsar uses an [Authentication Provider](#authentication) or an [Authentication Provider Chain](security-extending.md/#proxybroker-authentication-plugin) to establish the identity of a client and then assign a *role token* (a string like `admin` or `app1`)to that client. This role token can represent a single client or multiple clients and is then used for [Authorization](security-authorization.md) to determine what the client is authorized to do. You can use roles to control perm [...]
 
-The broker supports learning whether a particular client supports authentication refreshing. If a client supports authentication refreshing and the credential is expired, the authentication provider calls the `refreshAuthentication` method to initiate the refreshing process. If a client does not support authentication refreshing and the credential is expired, the broker disconnects the client.
+## Encryption
 
-You had better secure the service components in your Apache Pulsar deployment.
+Encryption ensures that if an attacker gets access to your data, the attacker cannot read the data without also having access to the encryption keys. Encryption provides an important mechanism for protecting your data at-rest and in-transit to meet your security requirements for cryptographic algorithms and key management. 
 
-## Role tokens
+**What's next?**
+* To configure end-to-end encryption, see [End-to-end encryption](security-encryption.md) for more details.
+* To configure transport layer encryption, see [TLS encryption](security-tls-transport.md) for more details.
 
-In Pulsar, a *role* is a string, like `admin` or `app1`, which can represent a single client or multiple clients. You can use roles to control permission for clients to produce or consume from certain topics, administer the configuration for tenants, and so on.
+## Authentication
 
-Apache Pulsar uses an [Authentication Provider](#authentication-providers) or an [Authentication Provider Chain](security-extending.md/#proxybroker-authentication-plugin) to establish the identity of a client and then assign a *role token* to that client. This role token is then used for [Authorization and ACLs](security-authorization.md) to determine what the client is authorized to do.
+Authentication is the process of verifying the identity of clients. In Pulsar, the authentication provider is responsible for properly identifying clients and associating the clients with role tokens. If you only enable authentication, an authenticated role token can access all resources in the cluster. 
 
-## Authentication providers
+Pulsar supports a pluggable authentication mechanism, and Pulsar clients use this mechanism to authenticate with brokers and proxies. 
 
-Currently, Pulsar supports the following authentication providers:
+Pulsar broker validates the authentication credentials when a connection is established. After the initial connection is authenticated, the "principal" token is stored for authorization though the connection is not re-authenticated. The broker periodically checks the expiration status of every `ServerCnx` object. By default, the `authenticationRefreshCheckSeconds` is set to 60s. When the authentication is expired, the broker re-authenticates the connection. If the re-authentication fails [...]
+
+Pulsar broker supports learning whether a particular client supports authentication refreshing. If a client supports authentication refreshing and the credential is expired, the authentication provider calls the `refreshAuthentication` method to initiate the refreshing process. If a client does not support authentication refreshing and the credential is expired, the broker disconnects the client.
 
+**What's next?**
+Currently, Pulsar supports the following authentication providers:
 - [TLS authentication](security-tls-authentication.md)
 - [Athenz authentication](security-athenz.md)
 - [Kerberos authentication](security-kerberos.md)
 - [JSON Web Token (JWT) authentication](security-jwt.md)
 - [OAuth 2.0 authentication](security-oauth2.md)
 - [HTTP basic authentication](security-basic-auth.md)
+You can also configure Pulsar to support multiple authentication providers.
+
+:::note
+
+Starting from 2.11.0, [TLS authentication](security-tls-authentication.md) includes [TLS encryption](security-tls-transport.md) by default. If you configure TLS authentication first, then TLS encryption automatically applies; if you configure TLS encryption first, you can select any one of the above authentication providers.
+
+:::
+
+## Authorization
 
+[Authorization](security-authorization.md) is the process of giving permissions to clients and determining what clients can do.
 
+The role tokens with the most permissions are the superusers who can create and delete tenants, along with full access to all tenant resources. When a superuser creates a tenant, that tenant is assigned an admin role token. A client with the admin role token can then create, modify and destroy namespaces, and grant and revoke permissions to other role tokens on those namespaces.
diff --git a/site2/website-next/static/assets/pulsar-encryption.svg b/site2/website-next/static/assets/pulsar-encryption.svg
new file mode 100644
index 00000000000..21d1a2a0930
--- /dev/null
+++ b/site2/website-next/static/assets/pulsar-encryption.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:lucid="lucid" width="2108.33" height="420.87"><g transform="translate(-18.746783964459837 867.2597739494072)" lucid:page-tab-id="0_0"><path d="M0-1258.83h3677.73V64H0z" fill="#fff"/><path d="M1301.86-841.26a6 6 0 0 1 6-6h793.22a6 6 0 0 1 6 6v368.87a6 6 0 0 1-6 6h-793.22a6 6 0 0 1-6-6z" stroke="#5e5e5e" stroke-width="2" fill="#fff"/><use xlink:href="#a" transform="matrix(1,0,0,1,1306.857120948584,-842 [...]
\ No newline at end of file