环境安装
在此案例中,使用阿里云服务器。(Linux)
使用官方安装脚本自动安装
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
- 安装fun
npm install @alicloud/fun -g
- 配置fun,按提示输入信息
fun config
基础:创建Helloworld文件
1. 创建一个文件夹,如image_crawler
2. 创建一个文件template.yml,内容
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
localdemo:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'local invoke demo'
image-crawler:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: index.handler
CodeUri: code/
Description: 'Hello world with python2.7!'
Runtime: python2.7
3. 创建一个code文件夹,在文件夹中编写helloworld代码
def handler(event, context):
return 'hello world!'
4. 运行函数
fun local invoke image-crawler
进阶:设置oss转存任务,如一个image_crawler
- 获取网页源代码,按上述语句运行image-crawler,可看到变化。
import logging
import json
import urllib
logger = logging.getLogger()
def handler(event, context):
logger.info("event: " + event)
evt = json.loads(event)
url = evt['url']
html = get_html(url)
logger.info("html content length: " + str(len(html)))
return 'Done!'
def get_html(url):
page = urllib.urlopen(url)
html = page.read()
return html
- 运行以下语句可看到变化
echo '{"url":"http://huaban.com/search/?q=%e5%a3%81%e7%ba%b8"}' | fun local invoke image-crawler
- 添加函数,从源代码中抽取图片路径
def get_img(html):
reg = r'https:\/\/[^\s,"]*\.jpg'
imgre = re.compile(reg)
return re.findall(imgre, html)
- 调整替换原先的handler函数,使之从“获取网页源代码”功能转变为“获取图片路径功能”。
def handler(event, context):
logger.info("event: " + event)
evt = json.loads(event)
url = evt['url']
html = get_html(url)
img_list = get_img(html)
logger.info(img_list)
return 'Done!'
- 将图片上传到OSS中,在 template 中配置环境变量(需提前创建好 oss bucket):
EnvironmentVariables:
OSSEndpoint: oss-cn-hangzhou.aliyuncs.com
BucketName: fun-local-test
- 然后就可以直接在函数中获取到这两个环境变量了:
endpoint = os.environ['OSSEndpoint']
bucket_name = os.environ['BucketName']
- 设置OSS的STS权限控制,参考如下代码
creds = context.credentials
if (local):
auth = oss2.Auth(creds.access_key_id,
creds.access_key_secret)
else:
auth = oss2.StsAuth(creds.access_key_id,
creds.access_key_secret,
creds.security_token)
bucket = oss2.Bucket(auth, endpoint, bucket_name)
- 遍历所有图片文件,并且转存到OSS中
count = 0
for item in img_list:
count += 1
logging.info(item)
# Get each picture
pic = urllib.urlopen(item)
# Store all the pictures in oss bucket, keyed by timestamp in microsecond unit
bucket.put_object(str(datetime.datetime.now().microsecond) + '.png', pic)
- 完整的代码
import logging,datetime
import json,re,oss2
import requests,urllib,os
logger = logging.getLogger()
endpoint = os.environ['OSSEndpoint']
bucket_name = os.environ['BucketName']
local = 1
def handler(event, context):
logger.info("event: " + event)
evt = json.loads(event)
url = evt['url']
print(url)
creds = context.credentials
if (local):
auth = oss2.Auth(creds.access_key_id,creds.access_key_secret)
else:
auth = oss2.StsAuth(creds.access_key_id,creds.access_key_secret,creds.security_token)
bucket = oss2.Bucket(auth, endpoint, bucket_name)
html = get_html(url)
img_list = get_img(html)
logger.info(img_list)
iii(img_list,bucket)
return 'Done!'
def iii(img_list,bucket):
count = 0
for item in img_list:
count += 1
logging.info(item)
pic = urllib.urlopen(item)
if pic != None:
bucket.put_object(str(datetime.datetime.now().microsecond) + '.jpg', pic)
def get_img(html):
reg = r'http:\/\/[^,"]*\.jpg'
imgre =re.compile(reg)
return re.findall(imgre,html)
def get_html(url):
page = requests.get(url)
html = page.content
return html
- 此时运行如下命令可看到成功效果。
echo '{"url":"http://huaban.com/search/?q=%e5%a3%81%e7%ba%b8"}' | fun local invoke image-crawler
部署
- 添加OSS权限到yaml中,此次是添加了policies:AliyunOSSFullAccess。注意localdemo这个函数计算项目及image-crawler这个函数,fun-local-test这个OSS项目bucket需要事先在阿里云官网后台配置过。
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
localdemo:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'local invoke demo'
Policies: AliyunOSSFullAccess
image-crawler:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: index.handler
CodeUri: code/
Description: 'Hello world with python2.7!'
Runtime: python2.7
EnvironmentVariables:
OSSEndpoint: oss-cn-hangzhou.aliyuncs.com
BucketName: fun-local-test
- 使用fun deploy 即看到运行成功。
- 登录阿里云函数计算后台,可以看到这个项目代码,可以线上修改配置。
思考:函数计算适合做什么用途?
定时任务,如爬虫类。(图片转存、文字转存等)
pipeline类别,如接受A信息,转存到B信息及格式。根据if,else等来分类的任务。
微信,钉钉等公众号的后端(Flask),免去搭建服务器。
可以一个函数就解决的任务与项目,特别简单的项目。
阿里云官方函数计算后台提供Flask-web类型的函数计算模块,可以快速搭建外网api可访问的接口与页面。
似乎不适合多轮交互的情况(也可能是我不知道)。
威胁建模与安全方面考虑:
通过这种方式,若是允许外网访问(触发器允许HTTP),似乎易受CSRF、越权漏洞攻击。
近期阿里云函数计算更新模块,所有HTTP通过浏览器访问会默认变成将Response下载到本地,因此不会存在XSS风险。(除非本地又渲染了)
Json劫持模块还没测试,如果返回值写的是Jsonp,那么因写法太灵活,也是易受Json劫持漏洞攻击的。
如果以一个serverless租户的身份写扫描器去扫描宿主机,会不会影响到其他租户的安全与稳定性?(待测试)