我想使用AWS Lambda运行用户通过Web提交的JavaScript代码。我的Lambda函数将返回返回值stderr
和stdout
。我这样做会遇到什么问题?
恶意用户是否能够提交导致Lambda函数出现问题的代码?用户对节点环境或文件系统所做的更改是否在调用之间持久存在?有什么办法可以防止这种情况?
代替eval()
我可以将文件写入Lambda文件系统并调用:
const userCodeProcess = require('child_process').fork('user_code.js')
userCodeProcess.on('message', response.send)
最佳答案
用户将能够向您的Lambda函数提交代码,这在某些情况下可能会引起问题:
文件系统-您的用户可以提交可以对文件系统进行更改的代码,并且这些更改将在重用容器上调用的函数之间保持不变。并非所有用户代码请求都将在同一容器上运行,但是如果将两个请求紧密靠近在一起,则可以访问同一容器,并且可以访问相同的“临时”磁盘空间。一种可能防止这种情况的方法是,如果可以将包括的功能(例如fs
)限制为在函数调用时定义的特定目录,以便可以为/tmp
目录中的每个请求创建一个随机目录。我不确定这是否可能。您必须确保用户自己不再需要fs
。更好的建议是使用safe-eval
之类的东西,我将在后面讨论。
环境变量-在eval中运行的代码可以访问Node环境变量。如果您需要对数据库,其他AWS产品等进行任何请求,则需要为Lambda函数提供一个策略,除非您对凭据进行硬编码,并且该信息可以由用户代码访问。您必须确保提供给系统的任何凭据都不在环境变量中,如果有,则确保用户可以访问它们。
节流-您可能会遇到节流问题。默认情况下,AWS仅允许100个并发调用。如果您不限制用户提交自己的JS的请求,那么您可能会遇到由于达到限制而被拒绝的问题。我最近请求增加限制,并且我能够将我的请求增加到3000个并发请求,而不必评估他们当前的基础结构是否可以处理它,因此它们也可以使您毫无问题。
费用-我确定您已经考虑过函数超时,但是您想确保确定函数运行时间的上限,以便用户不会浪费您的AWS账单。此外,它看起来似乎很小,但是在大规模情况下会增加一堆6MB的请求响应,因此数据的传入和传出可能会很麻烦,并且您可能希望将其限制在代码内。
限制您的用户可能会遇到容器/tmp
目录的限制。它们可能会遇到最大有效负载返回大小的问题。其他极限问题可以在here中进行研究。
据我了解,您无法使用代码破坏Lambda函数容器,以免将来的请求无法运行。我相信,如果现有容器不存在,或者现有容器遇到问题,则会启动一个新容器。
建议
根据我刚刚做的一些其他研究,您可能希望在某种上下文中运行javascript代码,以便您的用户只能访问所需的Node API端点以及您自己的系统定义的变量。使用safe-eval
之类的工具可能会起作用。其他人已经问过要在上下文中执行eval
的问题,例如here,或者您可以在每次调用use strict;
时在eval
之前加上stderr
并定义函数变量,例如here所述。
此外,在关闭函数并返回stdout
和/tmp
之前,您只需清除/tmp
目录即可。我对此的担心是,AWS在同时执行两个请求时是否利用同一个容器,并且您删除了同时执行的两个函数的“临时”空间。我无法在研究中找到决定性的答案。
在这一点上,我仍然要说,您的
从AWS上获得的其他有关容器重用的信息是here。
关于node.js - 在AWS Lambda中使用JavaScript eval(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42103256/