返回文章列表

Lambda 程式碼簽署容器佈署與資料自動匯入

本文探討如何在 AWS Lambda 中使用程式碼簽署和容器映像佈署,確保程式碼安全性和完整性,並示範如何利用 S3 事件觸發器自動將 CSV 資料匯入 DynamoDB。文章涵蓋了使用 AWS Signer 對 Lambda 函式程式碼進行簽署、使用 Docker 建立容器映像並佈署至 ECR,以及組態 S3

無伺服器運算 資料函式庫

在無伺服器架構中,程式碼安全性和自動化資料處理至關重要。本文介紹如何利用 AWS Signer 確保 Lambda 函式程式碼的完整性,並使用容器映像簡化佈署流程。同時,我們將示範如何設定 S3 事件觸發器,實作 CSV 資料自動匯入 DynamoDB,提升資料處理效率。此方案結合了程式碼安全、容器化佈署和自動化資料流程,是構建安全可靠的無伺服器應用程式的最佳實務。

在 Lambda 中使用 AWS Signer 執行受信任的程式碼

問題描述

開發者需要確保佈署在無伺服器環境中的函式程式碼來源是受信任的,並且需要驗證程式碼的完整性,以確保程式碼在簽署後未被修改。

解決方案

首先,建立一個簽署設定檔(signing profile),然後使用 AWS Signer 對程式碼進行簽署作業。最後,佈署一個 Lambda 函式,參考簽署設定並使用已簽署的程式碼。

準備工作

  • 具備版本控制的 S3 儲存桶,並將原始碼複製到該儲存桶中。
  • 為 AWS Signer 指定一個目標 S3 儲存桶。
  • 一個允許 Lambda 函式執行的 IAM 角色(在章節的先決條件中提供)。

步驟

  1. 取得 S3 物件版本

    OBJ_VER_ID=$(aws s3api list-object-versions \
    --bucket awscookbook505-src-$RANDOM_STRING \
    --prefix lambda_function.zip \
    --output text --query Versions[0].VersionId)
    
  2. 建立簽署設定檔

    SIGNING_PROFILE_ARN=$(aws signer put-signing-profile \
    --profile-name AWSCookbook505_$RANDOM_STRING \
    --platform AWSLambda-SHA384-ECDSA \
    --output text --query arn)
    
  3. 建立 Lambda 的程式碼簽署設定

    CODE_SIGNING_CONFIG_ARN=$(aws lambda create-code-signing-config \
    --allowed-publishers SigningProfileVersionArns=$SIGNING_PROFILE_ARN \
    --output text --query CodeSigningConfig.CodeSigningConfigArn)
    
  4. 啟動簽署作業

    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)
    
  5. 驗證簽署作業結果

    aws signer list-signing-jobs --status Succeeded
    
  6. 取得已簽署程式碼的 S3 物件金鑰

    OBJECT_KEY=$(aws s3api list-objects-v2 \
    --bucket awscookbook505-dst-$RANDOM_STRING \
    --prefix 'signed-' \
    --output text --query Contents[0].Key)
    
  7. 建立使用已簽署程式碼的 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,可以確保只執行受信任的程式碼,從而滿足合規要求並提高應用程式的安全態勢。

挑戰

  1. 修改原始碼,重新簽署並更新 Lambda 函式。
  2. 將 CodeSigningPolicies 從 Warn 改為 Enforce,以在驗證簽章失敗時阻止佈署。佈署一個利用此功能的函式,以確保只執行已簽署的程式碼。

將 Lambda 程式碼封裝在容器映像中佈署

準備工作

在開始之前,請確保您具備以下條件:

  • 一個 ECR 儲存函式庫
  • 一個允許 Lambda 函式執行的 IAM 角色(在章節準備工作中提供)
  • 已安裝 Docker

步驟說明

  1. 取得 ECR 登入資訊並傳遞給 Docker

    aws ecr get-login-password | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
    

    成功登入後,您應該會看到「Login Succeeded」的輸出。

  2. 建立一個名為 app.py 的檔案,並在其中加入您希望在 Lambda 中執行的程式碼(檔案已在儲存函式庫中提供):

    import sys
    def handler(event, context):
        return 'Hello from the AWS Cookbook ' + sys.version + '!'
    
  3. 建立一個名為 Dockerfile 的檔案,該檔案根據 AWS 提供的基礎映像,並參照您的 Python 程式碼(檔案已在儲存函式庫中提供):

    FROM public.ecr.aws/lambda/python:3.8
    COPY app.py ./
    CMD ["app.handler"]
    
  4. 在包含 Dockerfileapp.py 的資料夾中建立容器映像。此過程需要幾分鐘才能完成:

    docker build -t aws-cookbook506-image .
    
  5. 為映像新增額外的標籤,以便將其推播到 ECR

    docker tag aws-cookbook506-image:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-506repo:latest
    
  6. 將映像推播到 ECR 儲存函式庫。此過程需要幾分鐘才能完成:

    docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/aws-cookbook-506repo:latest
    
  7. 使用 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 引數。

  8. 驗證 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 的流程。

詳細步驟

  1. 導航至本章節儲存函式庫中的本配方目錄

    cd 507-Importing-CSV-to-DynamoDB-from-S3
    
  2. 建立一個 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'
    
  3. 設定一個唯一的字尾,用於 S3 貯體名稱

    RANDOM_STRING=$(aws secretsmanager get-random-password --exclude-punctuation --exclude-uppercase --password-length 6 --require-each-included-type --output text --query RandomPassword)
    
  4. 建立一個 S3 貯體

    aws s3api create-bucket --bucket awscookbook507-$RANDOM_STRING
    
  5. 為 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 中的過程。