Amazon web services 执行任意二进制文件时不允许执行操作
在中,AWS解释道: 包含您自己的可执行文件很容易;只需将它们打包到上载的ZIP文件中,然后在从Node.js或之前启动的其他进程调用它们时引用它们(包括创建的ZIP文件中的相对路径)。确保在功能代码的开头包含以下内容: process.env['PATH']=process.env['PATH']+':'+process.env['LAMBDA_TASK_ROOT'] 您可以使用所有常用的进程间通信形式以及/tmp中的文件与您创建的任何进程进行通信 我想在我的代码中使用Go Terraform libraryAmazon web services 执行任意二进制文件时不允许执行操作,amazon-web-services,go,aws-lambda,terraform,Amazon Web Services,Go,Aws Lambda,Terraform,在中,AWS解释道: 包含您自己的可执行文件很容易;只需将它们打包到上载的ZIP文件中,然后在从Node.js或之前启动的其他进程调用它们时引用它们(包括创建的ZIP文件中的相对路径)。确保在功能代码的开头包含以下内容: process.env['PATH']=process.env['PATH']+':'+process.env['LAMBDA_TASK_ROOT'] 您可以使用所有常用的进程间通信形式以及/tmp中的文件与您创建的任何进程进行通信 我想在我的代码中使用Go Terraform
tfexec
,但我总是被拒绝
main/tf中的代码
:
package main
import (
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/aws/aws-lambda-go/lambda"
"github.com/hashicorp/terraform-exec/tfexec"
)
func Start() error {
fmt.Printf("Go version: %s\n", runtime.Version())
fmt.Println()
// set environment variable, cf https://aws.amazon.com/blogs/compute/running-executables-in-aws-lambda/
newPath := []string{
os.Getenv("PATH"),
":",
os.Getenv("LAMBDA_TASK_ROOT"),
}
os.Setenv("PATH", strings.Join(newPath, ""))
// Get path to binary
fmt.Println("Start terraform")
currDir, err := os.Getwd()
if err != nil {
return err
}
tfBinary := filepath.Join(currDir, "terraform")
stat, err := os.Stat(tfBinary)
if err != nil {
return err
}
fmt.Printf("Stat %s: ", tfBinary)
fmt.Println(stat.Mode())
// Start new instance of terraform
tf, err := tfexec.NewTerraform(currDir, tfBinary)
if err != nil {
return err
}
tf.SetStdout(os.Stdout)
tf.SetStderr(os.Stderr)
// run terraform init
fmt.Println("Tf init")
if err = tf.Init(context.Background()); err != nil {
return err
}
return nil
}
func main() {
// Start()
lambda.Start(Start)
}
设置:
curl -X GET -o terraform https://releases.hashicorp.com/terraform/0.12.29/terraform_0.12.29_linux_amd64.zip
chmod 755 terraform
GOOS=linux GOARCH=amd64 go build create-vpc-tf.go
zip zip.zip terraform main
# Create Lambda running on go1.x with `main` as handler
结果:
START RequestId: f23e4122-3595-48ef-808f-ef7951531f59 Version: $LATEST
Go version: go1.16
Start terraform
Stat /var/task/terraform: -rwxr-xr-x
Tf init
fork/exec /var/task/terraform: operation not permitted
fork/exec /var/task/terraform: operation not permitted: PathError
null
END RequestId: f23e4122-3595-48ef-808f-ef7951531f59
REPORT RequestId: f23e4122-3595-48ef-808f-ef7951531f59 Duration: 2.26 ms Billed Duration: 3 ms Memory Size: 512 MB Max Memory Used: 32 MB Init Duration: 83.85 ms
这在本地可以正常工作(我没有提供
*.tf
文件,所以terraform正确地报告在空目录中初始化的terraform!
您已经下载了terraform二进制文件作为zip文件,因此它的格式无法执行
在使用zip
重新打包之前,您需要对其进行解压缩
替换:
curl -X GET -o terraform https://releases.hashicorp.com/terraform/0.12.29/terraform_0.12.29_linux_amd64.zip
与:
当您在本地运行此程序时,应该会看到如下内容: 你的Terraform版本已经过时了 因为问题中使用的是…过时了 如果您没有看到这样的消息,则表明您的本地测试实际上没有使用您在显示的安装程序中下载的文件
下载Terraform二进制文件的更安全的方法 或者,您可以使用
tfinstall
在运行时下载并隐式解压缩最新版本,如中所示
此方法使用Hashicorp的自定义下载程序,该程序同时执行。tfinstall甚至使用Hashicorp的公钥,以确保校验和文件本身未被篡改
如果您希望避免每次运行时下载terraform,您可以在本地使用
tfinstall
,并捕获结果以供重用(基本上只是在您的设置中替换curl
).此问题与tfexec
库及其在AWS lambda/Fire鞭炮环境中的可操作性有关。不允许在Fire鞭炮环境中分叉进程
Pdeathsig
强制使用叉,因此不能在AWS lambda中使用
Terraform本身不使用它,但tfexec
使用它
例如,谷歌快速搜索显示,其他项目也遇到了同样的问题
我们打包了显示的修复程序,以防止设置Pdeathsig
。这是对tfexec
库的直接更改,希望它们能够吸收上游。同时,我们在供应商
目录中直接打包tfexec
,并直接使用go mod
进行更改很好用
go mod init [repo]
go mod download
go mod vendor
更新供应商/github.com/hashicorp/terraform exec/tfexec/cmd_linux.go如下:
if _, ok := os.LookupEnv("LAMBDA_TASK_ROOT"); !ok {
cmd.SysProcAttr = &syscall.SysProcAttr{
// kill children if parent is dead
Pdeathsig: syscall.SIGKILL,
// set process group ID
Setpgid: true,
}
}
重建项目:go1.16 build main.go
重新打包并上传到您的lambda。在lambda中,
/var/task
是只读的。因此terraform init
将失败,因为它无法写入.terraform
目录。但是,由于您的错误消息表明fork或exec存在问题,这似乎不是问题。我发现一个错误可能会导致您出现一些问题ems…:)…但我无法解释它在本地是如何工作的,如果这确实是您运行的…提示-将此添加到您的脚本:文件terraform
以下是我认为我看到的。您已经下载了terraform\u 0.12.29\u linux\u amd64.zip
,然后尝试执行该.zip文件。它需要在某个点解压。我看不出有任何迹象表明NewTerraform不需要原始的可执行文件:下载后验证校验和也是一种良好的做法,如这里所述:,但是在解压之前你需要这样做。试图按照指示的gpg
指令进行操作会让我发疯。你可以tfinstall
直接获取二进制文件并验证其校验和。我最初是这样做的,但改变了我的方法,因为它导致了与帖子中所示相同的问题。我想在/tmp
文件夹上可能会有一个noexec
选项,出于安全原因,这是有意义的(/tmp
是唯一可写的文件夹,所以它是唯一可以下载的地方)。我选择参考AWS文档,其中建议直接打包二进制文件@Pauline,关于/tmp
文件夹:您可以从那里执行——我通过使用类似exec.Command(execPath,“init”).Run()的命令运行下载的二进制文件来验证。我还发现,正如您的回答所述,您可以在调用Run()
之前在SysProcAttr
中设置Pdeathsig:syscall.SIGKILL
,从而打破这一局面……但是,是的,我的回答只解决了问题中提出的部分问题。:)
go mod init [repo]
go mod download
go mod vendor
if _, ok := os.LookupEnv("LAMBDA_TASK_ROOT"); !ok {
cmd.SysProcAttr = &syscall.SysProcAttr{
// kill children if parent is dead
Pdeathsig: syscall.SIGKILL,
// set process group ID
Setpgid: true,
}
}