通过middleware对swift进行扩展

一,开发目的
本文会对swift进行扩展,开发一个查毒软件,对查出有毒的对象拒绝存储,并返回403状态码与查出的病毒
初步设计并实现了swift云存储的二次开发。
 
二,中间件原理
swift和其它openstack组件一样,使用paste建立http构架。paste是一个wsgi工具包,它提供了一个基于管道的体系构架。管道相当于两个应用之间的一个中间件,可以修改传入管道的请求或者回应,把修改过的请求或者回应交付给另一个管道,管道的最末尾是一个实际的应用,在swift中,管道的最末端是swift的代理服务器。
在swift中,默认的管道配置如下:
[pipeline:main]
pipeline = healthcheck proxy-logging cache tempauth proxy-logging proxy-server
当然,可以把tempauth替换成keystone,再加入tempurl ,ratelimit那些,我们将写的中间件扩展会位于temauth之后,理由很简单,对一个未认证的文件进行扫描,所需要的时间远大于对一个未扫描的文件进行认证。
 
三,查毒工具
我们使用clamav作为查毒引擎,这是一款开源的,免费的查毒引擎,只要提供一个ip和一个端口就可以连接该引擎并扫描某对象或者某对象流是否有病毒。
clamav的安装如下:
首先,安装clamav的基础组件
sudo apt-get install clamav-daemon clamav-freshclam clamav-unofficial-sigs
然后,启动更新病毒库配置文件
sudo freshclam
最后,启动杀毒服务
sudo service clamav-daemon start
 
通过python远程调用clamav也是一件很容易的事情,通过pip安装clamd库后,指明clamav服务器的ip和端口即可调用,下面的代码演示了如果通过1172.16.40.59:3310的远程服务器扫描一段病毒特征码
#!/usr/bin/python
# -*- coding: utf-8 -*-
AUTHOR = "leisurem"
 
import clamd
cd = clamd.ClamdNetworkSocket('172.16.40.59',3310)
from six import BytesIO as bi
print cd.instream(bi('X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*'))
 
扫描后,控制台提示:
{u'stream': (u'FOUND', u'Eicar-Test-Signature')}
说明扫描到该病毒特征码
 
四,初次实现
我们将要实现的SWGI中间件包含着一个可调用的对象,通常使用__call__方法,下面是一个基本范例:
#!/usr/bin/python
# -*- coding: utf-8 -*-
AUTHOR = "leisurem"
 
class SwiftClamavMiddleware(object):
    """此中间件会为swift执行病毒扫描"""
 
    def __init__(self, app, conf):
        # 初始化扫描病毒中间件,指定ip,端口等
        self.app = app
 
    def __call__(self, env, start_response):
        # 执行对象扫描
        return self.app(env, start_response)
 
 
def filter_factory(global_conf, **local_conf):
    conf = global_conf.copy()
    conf.update(local_conf)
 
    def clamav_filter(app):
        return SwiftClamavMiddleware(app, conf)
    return clamav_filter
 
我们在此实现了一个基本的,不做任何操作的中间件,它会接收请求,并将其返回,这已经很好了,下一步,我们会加入扫毒功能。
 
 
五,近一步实现
我们要检测病毒,比较好的设计方案为在文件传入时检测其是否正常,如果检测出异常,则返回403状态码,并禁止存入swift,如果正常,则通过管道将文件传给下一个app
 
#!/usr/bin/python
# -*- coding: utf-8 -*-
AUTHOR = "leisurem"
 
import clamd
from webob import Response
 
class SwiftClamavMiddleware(object):
    """Middleware doing virus scan for Swift."""
 
    def __init__(self, app, conf):
#        pyclamd.init_unix_socket('/var/run/clamav/clamd.ctl')
        self.cd = clamd.ClamdNetworkSocket()
        # app is the final application
        self.app = app
 
    def __call__(self, env, start_response):
        if env['REQUEST_METHOD'] == "PUT":
            # We have to read the whole content in memory because pyclamd
            # forces us to, but this is a bad idea if the file is huge.
 
            scan = self.cd.instream(env['wsgi.input'])
            if scan['stream'][0]=='FOUND':
                return Response(status=403,
                                body="Virus %s detected" % scan['stream'][1],
                                content_type="text/plain")(env, start_response)
        return self.app(env, start_response)
 
 
def filter_factory(global_conf, **local_conf):
    conf = global_conf.copy()
    conf.update(local_conf)
 
    def clamav_filter(app):
        return SwiftClamavMiddleware(app, conf)
    return clamav_filter
 
 
六,测试代码
1 配置中间件
打开/etc/swift/proxy-server.conf 
修改管道配置为:
[pipeline:main]
pipeline = healthcheck   proxy-logging  cache tempauth  tempurl  clamav proxy-logging proxy-server
 
增加clavmav的配置字段:
[filter:clamav]
paste.filter_factory = swiftclamav:filter_factory
 
保存/etc/swift/proxy-server.conf,载入新的配置文件:swift-init all reload即可
 
2 异常检测
在/home/swift/code/abc.txt  中保存'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*',并使用curl工具传入文件,返回403,提示拒绝原因:
 
curl -i -X PUT -T  /home/swift/code/abc.txt  -H "X-Auth-Token: AUTH_tk19b4e077035b4ec99fd56ac8d9db9efd"     http://127.0.0.1:8080/v1/AUTH_test/lei/abc.txt
HTTP/1.1 100 Continue
 
HTTP/1.1 403 Forbidden
Content-Type: text/plain; charset=UTF-8
Content-Length: 35
Date: Mon, 09 Dec 2013 14:20:33 GMT
 
Virus Eicar-Test-Signature detected
 
 
3 正常检测
修改上述abc.txt为正常文件,并使用curl工具重新传输,返回201,提示传输成功:
curl -i -X PUT -T  /home/swift/code/abc.txt  -H "X-Auth-Token: AUTH_tk19b4e077035b4ec99fd56ac8d9db9efd"    http://127.0.0.1:8080/v1/AUTH_test/lei/abc.txt
HTTP/1.1 100 Continue
 
HTTP/1.1 201 Created
Last-Modified: Mon, 09 Dec 2013 15:47:17 GMT
Content-Length: 0
Etag: d41d8cd98f00b204e9800998ecf8427e
Content-Type: text/html; charset=UTF-8
Date: Mon, 09 Dec 2013 15:47:17 GMT
 
 
七,近一步扩展
通过本文演示的方法,可以进一步扩展中间件,如在检测好的文件中加入X-Object-Meta-Scanned: safe字段
也可以检测传入的文件是否为图像,如果是图像,则使用PIL或imagemagick等生成缩略图,一并传入
也可以检测传入的文件是否为热点文件,如果是,则从缓存中返回该文件
 
 
注:本文参考了Julien Danjou的博客,原文代码无法使用,已重新改写,原文地址如下
http://julien.danjou.info/blog/2013/extending-swift-with-a-middleware-clamav
posted @ 2013-12-10 16:37  le.i  阅读(429)  评论(0编辑  收藏  举报