Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nacos configuration encryption/Nacos配置加密 #5367

Closed
robberphex opened this issue Apr 14, 2021 · 11 comments
Closed

Nacos configuration encryption/Nacos配置加密 #5367

robberphex opened this issue Apr 14, 2021 · 11 comments

Comments

@robberphex
Copy link
Contributor

Nacos configuration encryption/Nacos配置加密

Is your feature request related to a problem? Please describe.

Nacos storage configuration is stored in the database in plaintext, and the plaintext data can be obtained no matter in the database or at the transport layer (such as HTTP packet capture).

  • If the database content is leaked, all configuration items will be leaked
  • If the transport layer is captured, it will cause the configuration transported to leak

Describe the solution you'd like

If you need to encrypt the configuration, you need to transmit the cipher text at both the storage layer and the transport layer, and only decrypt it on the client.

Encryption can be done by a third-party encryption system (such as Alibaba Cloud kms) or implemented by yourself (such as AES algorithm). Currently, the restrictions of the third-party encryption system and Nacos are inconsistent. For example, KMS direct encryption does not support special characters, and only supports up to 16kb, etc. .
So using secondary encryption, the struct is as follows:

image

The specific client operation is shown in the figure:

image

The client must be able to identify the encrypted configuration, which can be identified by whether there is encryptedDataKey, or by other characteristics, such as by prefix.
For the convenience of user understanding, it is possible to identify whether the encryption configuration is configured at a glance, and it is recommended to use the prefix (cipher-) to identify it.
The encryption method must be extensible, and this one can be extended through SPI

Client implementation

As shown in the figure above, client modification mainly involves two parts:

Get Configuration

  • Since the body of the configuration interface (GET /nacos/v1/cs/configs) directly returns the content of the configuration, for encrypted configuration items, encryptedDataKey can only be added in the header.
  • Since the encryption algorithm is extensible, the Filter is implemented through SPI, and the acquisition and release of the filter configuration is unified, so that the decryption logic can be done in the Filter to obtain the plaintext configuration.
  • In addition, Filter will call a third-party service to decrypt, so Filter needs to read the required parameters from Properties, such as the authentication of the third-party system.

Publish Configuration

  • The configuration publishing interface (POST /nacos/v1/cs/configs) originally received the parameter content, and now you need to add an input parameter encryptedDataKey, and the nacos server will store the value in the database.
  • Since the encryption algorithm is extensible, the Filter is implemented through SPI. When the configuration is released, the Filter is used as the encryption logic to ensure that the configuration submitted to the Nacos server is ciphertext when the configuration is released.
  • Similarly, Filter will call a third-party service to encrypt, so Filter needs to read the required parameters from Properties, such as the authentication of the third-party system.

Modification

Client

  • Define the SPI extension point.
  • Implement the example Filter logic, taking encryption when publishing configuration and decryption when obtaining configuration as an example.

Server

  • The release configuration interface adds the encryptedDataKey parameter to the post parameter and stores it in the database.
  • Get the configuration interface to add encryptedDataKey parameter in the header and return it to the client.

背景

Nacos存储配置都是明文存储在数据库中,不管是在数据库里、还是在传输层(比如HTTP抓包),都能拿到明文数据。

  • 如果数据库内容泄露,会导致所有配置项泄露
  • 如果传输层被抓包,会导致传输的配置项泄露

解决方案

如果需要加密配置,则需要在存储层和传输层都传输密文,只在客户端解密。

加密可以由第三方加密系统来完成(比如阿里云kms)或者自己实现(比如AES算法),目前第三方加密系统和Nacos的限制并不一致,比如KMS直接加密不支持特殊字符,最大只支持16kb等。
所以使用二级加密,方案如下:

1614947486637-ad4de7cb-2a0a-48eb-befb-31d253cd6331

具体的客户端操作如图:

1614947522244-555e31de-3298-4819-8bab-2adf7bdbff95

客户端要能识别加密的配置,可以通过是否有encryptedDataKey来识别,也可以通过其他特征,比如通过前缀来识别。
为了用户理解方便,能够一眼识别出来是否加密配置,推荐通过前缀(cipher-)来识别。
加密方式必须可以扩展,这一块可以通过SPI来实现扩展点。扩展点的逻辑可以不同,比如cipher-前缀表示第三方系统直接加密,cipher-kms-aes-128-表示AES128,cipher-kms-aes-256-表示AES256等等,这一块的扩展性可以通过用户自己实现SPI来做到。

客户端实现

如上图所示,客户端修改主要涉及到两部分:

配置获取

  • 由于获取配置接口(GET /nacos/v1/cs/configs)的body直接返回了配置的内容,所以对于加密配置项来说,encryptedDataKey只能添加在header中。
  • 由于加密算法是可扩展的,所以通过SPI来实现Filter,统一过滤配置的获取和发布,这样就可以在Filter中做解密逻辑,从而获取明文配置了。
  • 另外,Filter会调用第三方服务来解密,所以Filter需要从Properties中读取所需的参数,比如第三方系统的认证等信息。

配置发布

  • 配置发布接口(POST /nacos/v1/cs/configs)本来就接收了参数content,现在需要增加一个入参encryptedDataKey,nacos服务端会存储该值到数据库中。
  • 由于加密算法是可扩展的,所以通过SPI来实现Filter,在发布配置的时候,Filter来做加密逻辑,从而确保发布配置时,提交到Nacos服务端的配置是密文的。
  • 同样的,Filter会调用第三方服务来加密,所以Filter需要从Properties中读取所需的参数,比如第三方系统的认证等信息。

修改点

客户端

  • 定义SPI扩展点。
  • 实现示例Filter逻辑,以发布配置时加密、获取配置时解密为例。

服务端

  • 发布配置接口在post参数中增加encryptedDataKey参数,并入库。
  • 获取配置接口在header中增加encryptedDataKey参数,返回给客户端。
@KomachiSion
Copy link
Collaborator

I have a question about this design.

For most of situation, users will input configuration before encrypting in console. Whether console need to connect third part system and do encrypt? What's more, when user query configuration in console, how to decrypt the configuration?

robberphex added a commit to robberphex/nacos that referenced this issue Apr 20, 2021
Co-authored-by: lidaoyang <lidaoyang@hotmail.com>
KomachiSion pushed a commit that referenced this issue Apr 20, 2021
Co-authored-by: lidaoyang <lidaoyang@hotmail.com>

Co-authored-by: lidaoyang <lidaoyang@hotmail.com>
@CherishCai
Copy link
Contributor

另外,传输层与客户端的加解密逻辑 和 落库取库的加解密 分开可不同实现是否更好?

In addition, is it better that the encryption and decryption logic of the transport layer and the client side and the encryption and decryption of the library can be implemented differently?

@zx0zx9zx1zx9
Copy link

请问下,配置加解密功能 在1.4版本上实现吗?

@catcherwong
Copy link
Contributor

修改点中的服务端部分似乎还没有实现?

@robberphex
Copy link
Contributor Author

修改点中的服务端部分似乎还没有实现?

是的,由于服务端需要实现配置加密的可扩展、可插拔,目前还没有比较好的插件方案,所以还没有实现。

@robberphex
Copy link
Contributor Author

请问下,配置加解密功能 在1.4版本上实现吗?

1.4.2 的client已经支持配置加密SPI扩展了

@gangxie112
Copy link

gangxie112 commented Jun 18, 2021

几个问题:

  1. 如果以这种方式加密,nacos界面上如何给用户显示明文,或者不显示明文?
  2. 用户如何在nacos对这些加密数据进行修改?比如数据库密码更新
  3. 这种方案是否考虑过大规模场景?特别实在容器环境下,大规模的客户端对加密基础设施的压力是否是一个潜在瓶颈?
  4. 使用和运维的复杂度前置。加解密的前置,必然导致加密线上问题的前置,而且加解密这些安全问题,往往是业务研发不太熟悉的,甚至是业务运维不太熟悉的,出了问题比较难定位。而且,用户自己需要维护一套密文/token管理体系/规则。

@gangxie112
Copy link

备注,在大多数私有云场景,idc内部,明文传输是没有问题的

@changhr2013
Copy link

changhr2013 commented Oct 28, 2021

Encrypt 草图

概念

  1. DEK:Data Encrypt Key,用于加密真实数据的密钥,原则上只应在加密系统内部流转,在加密系统外部以密文形式存在
  2. EDEK:Encrypted Data Encryption Key,DEK 的密文,如果 DEK 要由外部存储,需在加密系统内部被加密为 EDEK 后返回给外部系统。
  3. 公/私钥:客户端生成的一对公私钥,私钥由客户端持有,公钥上传到云端
  4. PBE 密钥:Web 端基于用户口令生成的管理密钥。
  5. CEEDEK:使用客户端公钥加密 EDEK 得到的密文,存储在服务器端,同密文配置一同下发给客户端。
  6. PEEDEK:使用 PBE 管理密钥加密 EDEK 得到的密文,存储在服务器端,同密文配置一同响应给 Web 端控制台。

交互流程

  1. 客户端生成一对公私钥,私钥配置在客户端,公钥上传至 Server,同时管理者设置一个用于管理配置的口令。
  2. 管理者输入口令后,在 Nacos Web 添加配置,并指定对应的客户端公钥,Nacos Web 访问加密系统加密配置,返回 EDEK和配置密文,使用公钥加密 EDEK 得到 CEEDEK,使用口令衍生出的 PBE 密钥加密 EDEK 得到 PEEDEK,连同密文一起提交给 Server 端落库存储。
  3. 客户端拉取配置时,Server 响应给客户端 CEEDEK 和密文,客户端使用私钥解密 CEEDEK 得到 EDEK,然后使用 EDEK 和密文请求加密系统解密配置得到原文。
  4. Nacos Web 要显示敏感配置时,Server 响应给 Web 端 PEEDEK 和 密文,管理者在 Web 端输入管理口令,通过口令衍生出 PBE 密钥,使用 PBE 密钥解密 PEEDEK 得到 EDEK,然后使用 EDEK 和 密文请求加密系统解密配置得到原文显示。

原则

  1. 加密系统用于加密敏感数据的密钥原则上不应流转到外部,加解密运算应该只在加密系统内部做运算。
  2. Server 端原则上无法通过任何方式解密出敏感配置原文,只有最终配置的使用方(Client 和 web)才能解密出敏感配置。
  3. 敏感配置和所有密钥原则上在存储和传输过程中都应该以密文形式存在,只有在最终使用时才解密出原文。

以上是一些关于敏感配置加密方案的思考。

@KomachiSion
Copy link
Collaborator

@Byhuang1998
Copy link

请问下,配置加解密功能 在1.4版本上实现吗?

希望在nacos上用密文保存密码,加载到项目中时通过某些手段(例如拦截器,或继承某个类)解密。这个能实现吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants