在無伺服器架構中,程式碼安全性和自動化資料處理至關重要。本文介紹如何利用 AWS Signer 確保 Lambda 函式程式碼的完整性,並使用容器映像簡化佈署流程。同時,我們將示範如何設定 S3 事件觸發器,實作 CSV 資料自動匯入 DynamoDB,提升資料處理效率。此方案結合了程式碼安全、容器化佈署和自動化資料流程,是構建安全可靠的無伺服器應用程式的最佳實務。
在 Lambda 中使用 AWS Signer 執行受信任的程式碼
問題描述
開發者需要確保佈署在無伺服器環境中的函式程式碼來源是受信任的,並且需要驗證程式碼的完整性,以確保程式碼在簽署後未被修改。
解決方案
首先,建立一個簽署設定檔(signing profile),然後使用 AWS Signer 對程式碼進行簽署作業。最後,佈署一個 Lambda 函式,參考簽署設定並使用已簽署的程式碼。
準備工作
- 具備版本控制的 S3 儲存桶,並將原始碼複製到該儲存桶中。
- 為 AWS Signer 指定一個目標 S3 儲存桶。
- 一個允許 Lambda 函式執行的 IAM 角色(在章節的先決條件中提供)。
步驟
取得 S3 物件版本
OBJ_VER_ID=$(aws s3api list-object-versions \ --bucket awscookbook505-src-$RANDOM_STRING \ --prefix lambda_function.zip \ --output text --query Versions[0].VersionId)建立簽署設定檔
SIGNING_PROFILE_ARN=$(aws signer put-signing-profile \ --profile-name AWSCookbook505_$RANDOM_STRING \ --platform AWSLambda-SHA384-ECDSA \ --output text --query arn)建立 Lambda 的程式碼簽署設定
CODE_SIGNING_CONFIG_ARN=$(aws lambda create-code-signing-config \ --allowed-publishers SigningProfileVersionArns=$SIGNING_PROFILE_ARN \ --output text --query CodeSigningConfig.CodeSigningConfigArn)啟動簽署作業
SIGNING_JOB_ID=$(aws signer start-signing-job \ --source 's3={bucketName=awscookbook505-src-'"$RANDOM_STRING"',key=lambda_function.zip,version='"$OBJ_VER_ID"'}' \ --destination 's3={bucketName=awscookbook505-dst-'"$RANDOM_STRING"',prefix=signed-}' \ --profile-name AWSCookbook505_$RANDOM_STRING \ --output text --query jobId)驗證簽署作業結果
aws signer list-signing-jobs --status Succeeded取得已簽署程式碼的 S3 物件金鑰
OBJECT_KEY=$(aws s3api list-objects-v2 \ --bucket awscookbook505-dst-$RANDOM_STRING \ --prefix 'signed-' \ --output text --query Contents[0].Key)建立使用已簽署程式碼的 Lambda 函式
LAMBDA_ARN=$(aws lambda create-function \ --function-name AWSCookbook505Lambda \ --runtime python3.8 \ --package-type "Zip" \ --code S3Bucket=awscookbook505-dst-$RANDOM_STRING,S3Key=$OBJECT_KEY \ --code-signing-config-arn $CODE_SIGNING_CONFIG_ARN \ --handler lambda_function.lambda_handler --publish \ --role arn:aws:iam::$AWS_ACCOUNT_ID:role/AWSCookbookLambdaRole \ --output text --query FunctionArn)
程式碼解析
簽署設定檔建立指令解析
SIGNING_PROFILE_ARN=$(aws signer put-signing-profile \
--profile-name AWSCookbook505_$RANDOM_STRING \
--platform AWSLambda-SHA384-ECDSA \
--output text --query arn)
此指令用於建立一個簽署設定檔,其中 --platform AWSLambda-SHA384-ECDSA 指定了簽署平台。輸出結果中的 arn 即為簽署設定檔的 ARN。
程式碼簽署設定建立指令解析
CODE_SIGNING_CONFIG_ARN=$(aws lambda create-code-signing-config \
--allowed-publishers SigningProfileVersionArns=$SIGNING_PROFILE_ARN \
--output text --query CodeSigningConfig.CodeSigningConfigArn)
此指令建立了一個 Lambda 的程式碼簽署設定,並指定了允許發布的簽署設定檔版本 ARN。
簽署作業啟動指令解析
SIGNING_JOB_ID=$(aws signer start-signing-job \
--source 's3={bucketName=awscookbook505-src-'"$RANDOM_STRING"',key=lambda_function.zip,version='"$OBJ_VER_ID"'}' \
--destination 's3={bucketName=awscookbook505-dst-'"$RANDOM_STRING"',prefix=signed-}' \
--profile-name AWSCookbook505_$RANDOM_STRING \
--output text --query jobId)
此指令啟動了一個簽署作業,指定了來源 S3 物件和目標 S3 儲存桶,以及使用的簽署設定檔名稱。
驗證與清理
- 驗證:檢視 Lambda 主控台中的函式,確認無法編輯程式碼,並顯示「Your function has signed code and can’t be edited inline.」訊息。
- 清理:按照章節程式碼儲存函式庫中該配方資料夾中的步驟進行清理。
討論
此方法允許安全導向的管理員和應用開發者實施 DevSecOps 策略,透過強制規則只允許受信任的程式碼佈署在給定的環境中。使用 AWS Signer,可以確保只執行受信任的程式碼,從而滿足合規要求並提高應用程式的安全態勢。
挑戰
- 修改原始碼,重新簽署並更新 Lambda 函式。
- 將 CodeSigningPolicies 從 Warn 改為 Enforce,以在驗證簽章失敗時阻止佈署。佈署一個利用此功能的函式,以確保只執行已簽署的程式碼。
將 Lambda 程式碼封裝在容器映像中佈署
準備工作
在開始之前,請確保您具備以下條件:
- 一個 ECR 儲存函式庫
- 一個允許 Lambda 函式執行的 IAM 角色(在章節準備工作中提供)
- 已安裝 Docker
步驟說明
取得 ECR 登入資訊並傳遞給 Docker:
aws ecr get-login-password | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com成功登入後,您應該會看到「Login Succeeded」的輸出。
建立一個名為
app.py的檔案,並在其中加入您希望在 Lambda 中執行的程式碼(檔案已在儲存函式庫中提供):import sys def handler(event, context): return 'Hello from the AWS Cookbook ' + sys.version + '!'建立一個名為
Dockerfile的檔案,該檔案根據 AWS 提供的基礎映像,並參照您的 Python 程式碼(檔案已在儲存函式庫中提供):FROM public.ecr.aws/lambda/python:3.8 COPY app.py ./ CMD ["app.handler"]在包含
Dockerfile和app.py的資料夾中建立容器映像。此過程需要幾分鐘才能完成:docker build -t aws-cookbook506-image .為映像新增額外的標籤,以便將其推播到 ECR:
docker tag aws-cookbook506-image:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-506repo:latest將映像推播到 ECR 儲存函式庫。此過程需要幾分鐘才能完成:
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-506repo:latest使用 Docker 映像建立 Lambda 函式,指定
--code值為 Docker 映像的ImageUri:LAMBDA_ARN=$(aws lambda create-function --function-name AWSCookbook506Lambda --package-type "Image" --code ImageUri=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-506repo:latest --role arn:aws:iam::$AWS_ACCOUNT_ID:role/AWSCookbookLambdaRole --output text --query FunctionArn)當建立使用容器映像的函式時,不需要或支援
--runtime和--handler引數。驗證 Lambda 函式是否已進入活動狀態:
aws lambda get-function --function-name $LAMBDA_ARN --output text --query Configuration.State
驗證檢查
- 在 AWS 控制檯中,導航至 Lambda → Functions 選單。
- 注意您的函式的「Package type」為 Image。
- 呼叫函式並查看回應:您應該會看到類別似以下的輸出:
aws lambda invoke --function-name $LAMBDA_ARN response.json && cat response.json{ "StatusCode": 200, "ExecutedVersion": "$LATEST" } "Hello from the AWS Cookbook 3.8.8 (default, Mar 8 2021, 20:13:42) \n[GCC 7.3.1 20180712 (Red Hat 7.3.1-12)]!"
清理工作
請按照本章節程式碼儲存函式庫中的本配方資料夾中的步驟進行清理。
詳細解析
將應用程式碼封裝在容器映像中的好處
如果您的應用程式碼封裝在容器映像中,AWS Lambda 提供將您的函式程式碼封裝在容器映像中的能力。這使得與您可能已經使用的現有建置、測試、封裝和佈署管道保持一致。您可以為您的函式封裝大小最多可達 10 GB 的應用程式碼。您可以使用 AWS 提供的基本映像或建立自己的映像,只要您包含 Lambda 執行環境所需的執行時介面客戶端即可。
將容器映像儲存在 Amazon ECR 中
您可以將您的容器映像儲存在 Amazon ECR 中,並且您的函式必須與您儲存容器映像的 ECR 儲存函式庫位於同一帳戶中。
挑戰任務
更新應用程式碼,建立新的映像,將其推播到 ECR,並更新 Lambda 函式。
將 CSV 資料從 S3 自動匯入 DynamoDB 使用 Lambda
問題描述
當檔案上傳到 S3 時,您需要將資料從 S3 載入 DynamoDB。
解決方案
使用 Lambda 函式將 S3 資料載入 DynamoDB,並組態 S3 通知,指定 Lambda 函式在 S3:PutObject 事件上觸發(參見圖 5-7)。
圖示說明:使用 Lambda 函式將資料載入 DynamoDB 表格
此圖示展示了使用 Lambda 函式將資料從 S3 載入 DynamoDB 的流程。
詳細步驟
導航至本章節儲存函式庫中的本配方目錄:
cd 507-Importing-CSV-to-DynamoDB-from-S3建立一個 DynamoDB 表格:
aws dynamodb create-table --table-name 'AWSCookbook507' --attribute-definitions 'AttributeName=UserID,AttributeType=S' --key-schema 'AttributeName=UserID,KeyType=HASH' --sse-specification 'Enabled=true,SSEType=KMS' --provisioned-throughput 'ReadCapacityUnits=5,WriteCapacityUnits=5'設定一個唯一的字尾,用於 S3 貯體名稱:
RANDOM_STRING=$(aws secretsmanager get-random-password --exclude-punctuation --exclude-uppercase --password-length 6 --require-each-included-type --output text --query RandomPassword)建立一個 S3 貯體:
aws s3api create-bucket --bucket awscookbook507-$RANDOM_STRING為 Lambda 函式建立一個角色,允許使用 S3 和 DynamoDB(檔案已在儲存函式庫中提供):
aws iam create-role --role-name AWSCookbook507Lambda --assume-role-policy-document file://assume-role-policy.json
程式碼解析
Dockerfile 解析
FROM public.ecr.aws/lambda/python:3.8
COPY app.py ./
CMD ["app.handler"]
此 Dockerfile 根據 AWS Lambda 的 Python 3.8 環境,將 app.py 複製到容器中,並設定預設的命令來執行 app.handler。
程式碼邏輯解析
app.py 解析
import sys
def handler(event, context):
return 'Hello from the AWS Cookbook ' + sys.version + '!'
此 Python 指令碼定義了一個 handler 函式,該函式是 Lambda 的入口點。它傳回一條訊息,包括 Python 版本資訊。
此圖示說明瞭使用 Lambda 將資料從 S3 載入 DynamoDB 的流程。
圖中展示了當檔案上傳到 S3 時,如何透過 S3 通知觸發 Lambda 函式,並由該函式將資料載入到 DynamoDB 中的過程。