安全

Introduction:引言

尽管Celery在编写时考虑到了安全,但它应该被视为不安全的组件。

根据你的安全策略open in new window,这儿有一些步骤可以让Celery更加安全

Areas of Concern:关注区域

Broker

必须保护broker免受不必要的访问,尤其是在公网的时候。默认情况下,workers相信从broker传过来的数据是未经篡改的。查看Message Signing获取关于如何让连接更可信的信息

第一道防线应该是一个放置在broker前的只允许白名单访问的防火墙。

很普遍的现象是防火墙配置错误或者被关闭。使用可靠的安全策略包括监控防火墙设备来检测它们是否被禁用,无论是意外还是故意的。

另一方面,也不能盲目信任防火墙。

如果你使用的broker有更细粒度的访问控制,比如RabbitMQ,那么你应该启用它。查看示例:http://www.rabbitmq.com/access-control.html

如果你使用的后端支持,你还可以使用broker_use_ssl来开启SSL加密和身份验证。

Client

In Celery, “client” refers to anything that sends messages to the broker, for example web-servers that apply tasks.

Having the broker properly secured doesn’t matter if arbitrary messages can be sent through a client.

[Need more text here]

Worker

tasks在worker中运行的权限和worker自身权限是一样的。这适用于资源,例如:内存、文件系统和设备。

此规则的一个例外是使用基于多处理的任务池时,这是当前的默认设置。在这种情况下,该任务将可以访问作为fork()调用的结果而复制的任何内存,并可以访问由同一个工作者子进程中的父任务写入的内存内容。

通过给每个任务启动一个子进程(fork() + execve()),可以限制对内存内容的访问。

限制文件系统的访问可以通过使用chroot, jail, sandboxing, virtual machines或其他由平台提供的特性或者第三方软件

Serializers:序列化

从4.0开始默认的序列化使用的是JSON,不过由于其数据类型受限,你可能希望使用 pickle 替代。

pickle 非常好用,它几乎可以序列化一切Python对象,甚至是包含work的函数。由于这个特性,其从根本上不安全[*],因此应该避免不受信任或未经身份验证的客户端使用。

通过在accept_content设置中指定接受的内容类型的白名单,可以禁用不受信任的内容:

3.0.18新增特性:

Note:

3.0.18以下不支持

accept_content = ['json']

它接受序列化名称和content-type的列表,因此您还可以指定json为content type:

accept_content = ['application/json']

Celery 还带有一个特殊的 auth 序列化程序,用于验证 Celery 客户端和workers之间的通信,确保消息来自可信来源。 使用公钥加密,auth 序列化程序可以验证发件人的真实性,要启用的话,阅读Message Signing获取更多信息。

Message Signing:消息签名

Celery可以使用cryptography库用公钥来对消息进行签名,客户端使用私钥对发送的消息进行签名,然后worker使用公开证书对其进行验证。

有正式的证书颁发机构签发的证书最好,当然自签名的也是可以的。

若要启用此功能,您应该将task_serializer设置为使用 auth 序列化程式。强制workers只接受签名消息,您应该将accept_content设置为*[']auth'*。For additional signing of the event protocol, set event_serializer to auth。还需要配置用于在文件系统上查找私钥和证书的路径:security_key、security_certificate和security_cert_store.您可以使用security_digest调整签名算法。

对于调用celery.setup_security() 函数来说这些配置是必要的。请注意,这还会禁用所有不安全的序列化程序,以便worker不会接受具有不受信任内容类型的消息。

这是一个配置了 auth 序列化程序的示例,私钥和证书位于 /etc/ssl

app = Celery()
app.conf.update(
    security_key='/etc/ssl/private/worker.key'
    security_certificate='/etc/ssl/certs/worker.pem'
    security_cert_store='/etc/ssl/certs/*.pem',
    security_digest='sha256',
    task_serializer='auth',
    event_serializer='auth',
    accept_content=['auth']
)
app.setup_security()

Note:

虽然不禁止使用相对路径,但建议对这些文件使用绝对路径。

还要注意,auth 序列化程序不会加密消息的内容,因此如果需要,必须单独启用它。

Intrusion Detection:入侵侦测

保护您的系统免受入侵者攻击时,最重要的部分是能够检测系统是否已被破坏。

Logs

日志通常是第一个用来确认是否遭受攻击的地方,不过一旦被篡改,也就没用了。

好的解决办法是使用专用的日志收集服务器集中收集日志。它们的访问应该是受限的。除了将所有日志放在一个位置之外,如果配置正确,它还可以使入侵者更难篡改您的日志。

使用syslog应该比较容易设置(查看syslog-ng open in new windowrsyslogopen in new window)。Celery使用的是loggingopen in new window库,并且已经支持syslog。

对偏执狂的一个提示是使用UDP发送日志,并切断日志服务器的网络电缆的传输部分:-)

Tripwire

Tripwireopen in new window是一个数据完整性工具(现在是商业化工具),通过几个开源项目实现,用来监控文件系统上的hashes值,以便于管理员可以及时受到警告当文件被改变时。通过这种方式,当系统被破坏之后你可以知道那些文件被更改了(密码文件, 日志, 后门, root-kits, 等等)。通常,这是您能够检测到入侵的唯一方法。

一些开源实现包括:

此外,ZFSopen in new window文件系统内置了完整性校验。