AWS Lambda 上的 .NET 工作負載

模組 4

模組 4:與其他 AWS 服務搭配使用

 學習模組

請注意,您可以按照此處提供的範例執行操作,但這並非強制要求。

使用其他 AWS 服務的方法有多種。

如果您存取的服務是 AWS RDS 資料庫 (例如 SQL Server 或 Postgres),則您使用的資料庫與您在自己的電腦或資料中心託管資料庫時使用的資料庫相同。您需要一個包含用戶名和密碼的連接字串,或者您選擇的其他身份驗證方式。與您日常使用資料庫的方式沒有什麼不同。您無需任何其他許可權即可存取資料庫伺服器。唯一需要注意的是,如果資料庫不可公開存取,則您需要將 Lambda 連接到 VPC (該過程需要額外的許可權)。

如果您的 Lambda 函數使用的是 S3、DynamoDB、Kinesis 等,則您可以使用 AWS SDK 與這些服務進行互動。Lambda 函數以之執行的角色需要適當的許可權才能與每項服務互動。例如,如果您想向 S3 儲存貯體新增專案,則該角色需要獲取許可權才能寫入該儲存貯體。如果您想從 DynamoDB 資料表中獲取項目,則該角色需要獲取許可權才能從該表中讀取項目。

第三種情況是,您希望其他服務觸發您的 Lambda 函數以回應某個事件。例如,您可能希望在向特定 S3 儲存貯體新增新項目,或者當事件到達 Kinesis 串流時觸發 Lambda 函數。為此,Lambda 函數必須使用「基於資源的政策」。此政策向其他服務提供調用您的 Lambda 函數的許可權。

 完成時間

30 分鐘 

透過 Lambda 函數存取 RDS 資料庫伺服器

使用熟悉的服務 (如 SQL Server、Postgres、MySQL) 的好處在於,從程式碼的角度來看,透過 Lambda 函式呼叫這些服務時無需任何不同於以往的操作。Entity Framework/ado/NpgSql 等與 AWS 託管資料庫一樣適用於本機/機架式資料庫。調用方式相同,您不需要 AWS SDK 資料庫,當然您仍然需要將相關的 NuGet 套件新增到您的專案中。但除此之外,都是一樣的。

透過 Lambda 函數存取 AWS 服務

如需存取大多數 AWS 服務,您需要授予 Lambda 函數與相應服務互動的許可權。為此,您可以向 Lambda 函數以之執行的角色新增政策。該政策需要授予 Lambda 函數與服務互動的許可權。您可以透過兩種方式建立政策:
1. 作為內聯政策,您只能將其用於該角色。

2.作為獨立政策,您可以將其附加到任何角色。在 AWS 中,後者被稱為客戶管理的政策。

向角色授予盡可能少的許可權始終是最佳做法。在以下範例中,您將從 DynamoDB 資料表中讀取資料,您需要向 Lambda 角色授予兩項許可權:dynamodb:GetItem 和 dynamodb:DescribeTable。您可以將這些許可權限於您感興趣的特定資料表。

首先,建立一個名為「People」的新 DynamoDB 資料表。如果您使用的是 Windows 命令提示符,則以下命令將適用於 PowerShell,而 Linux Shell 需要對字串進行不同的轉義處理。

執行以下命令:
aws dynamodb create-table --table-name People --attribute-definitions AttributeName=PersonId,AttributeType=N --key-schema AttributeName=PersonId,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
注意 TableArn,稍後您將用到它。它將位於輸出的底部附近。

向資料表中新增一些項目:
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"1"},"State":{"S":"MA"}, "FirstName": {"S":"Alice"}, "LastName": {"S":"Andrews"}}'
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"2"},"State":{"S":"MA"}, "FirstName": {"S":"Ben"}, "LastName": {"S":"Bradley"}}'
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"3"},"State":{"S":"MA"}, "FirstName": {"S":"Claire"}, "LastName": {"S":"Connor"}}'
您現在有一個資料表,其中有三個項目。

然後使用以下命令建立 Lambda 函數:
dotnet new lambda.EmptyFunction -n LambdaFunctionDynamoDB 
轉至 LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB 目錄,然後新增 AWSSDK.DynamoDBv2 NuGet 包:
cd LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB 
dotnet add package AWSSDK.DynamoDBv2
然後開啟 Function.cs 並將程式碼替換為以下內容:
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Lambda.Core;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace LambdaFunctionDynamoDB ;

public class Function
{
   public async Task<string> FunctionHandler(ILambdaContext lambdaContext)
 {
   AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig(); 
   AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig);
   DynamoDBContext dynamoDbContext = new DynamoDBContext(client);

   Person person = await dynamoDbContext.LoadAsync<Person>(1);

   return $"{person.FirstName} {person.LastName} lives in {person.State}";
 }
}

[DynamoDBTable("People")]
public class Person
{
    [DynamoDBHashKey]
    public int PersonId {get; set;}
    public string State {get; set;}
    public string FirstName {get; set;}
    public string LastName {get; set;}
}
使用以下程式碼將 Lambda 函數部署至 AWS Lambda:
dotnet lambda deploy-function LambdaFunctionDynamoDB

使用以下程式碼將 Lambda 函數部署至 AWS Lambda:

dotnet lambda deploy-function LambdaFunctionDynamoDB

接下來,系統將詢問您「選擇為您的程式碼提供 AWS 憑證的 IAM 角色:」,您可能會看到之前建立的角色清單,但清單底部將顯示「**建立新 IAM 角色***」選項,在該選項旁邊輸入該數位。

系統將要求您「輸入新 IAM 角色的名稱:」。輸入「LambdaFunctionDynamoDBRole」。

然後,系統將要求您「選擇要附加到新角色的 IAM 政策並授予許可權」,並顯示政策清單。選擇「AWSLambdaBasicExecutionRole」,它位於清單第 6 位。(我知道有一個名為「AWSLambdaDynamoDBExecutionRole」的政策,但是這個模組的目標是向您展示如何自行新增必要的許可權)。

嘗試使用以下命令調用 Lambda 函數:

dotnet lambda invoke-function LambdaFunctionDynamoDB 
您會收到一條很長的錯誤訊息,但在頂部附近您會看到如下所示的內容:
 "errorMessage": "User: arn:aws:sts::YOUR_ACCOUNT_NUMBER:assumed-role/LambdaFunctionDynamoDB Role/LambdaFunctionDynamoDB  is not authorized to perform: dynamodb:DescribeTable on resource: arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People because no identity-based policy allows the dynamodb:DescribeTable action"
請注意以下訊息:「...no identity-based policy allows the dynamodb:DescribeTable action」(……任何基於身份的政策都不允許 dynamodb:DescribeTable 操作)。

意思就是,Lambda 函數以之執行的角色未獲得所需的 dynamodb:DescribeTable 許可權。

要解決該問題,您需要新增一個政策,以向該角色授予 dynamodb:DescribeTable 許可權。如上所述,您可以新增內聯政策 (僅適用於此角色) 或獨立政策 (適用於所有角色)。

在 LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB 資料夾中建立一個名為「DynamoDBAccessPolicy.json」的檔案。

編輯 DynamoDBAccessPolicy,但請使用您在資源中的帳號:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DescribeTable"
            ],
            "Resource": "arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People"
        }
    ]
}
執行以下命令:
aws iam put-role-policy --role-name LambdaFunctionDynamoDBRole --policy-name LambdaFunctionDynamoDBAccess --policy-document file://DynamoDBAccessPolicy.json
該政策可能需要過一段時間才能生效。您可以等待幾分鐘,也可以重新部署 Lambda 函數。如果您想重新部署該函數,請執行以下命令:
dotnet lambda deploy-function LambdaFunctionDynamoDB 
部署 Lambda 函數後,您可以使用以下方法再次調用它:
dotnet lambda invoke-function LambdaFunctionDynamoDB
又出錯了!

這次的訊息是:
"errorMessage": "User: arn:aws:sts::YOUR_ACCOUNT_NUMBER:assumed-role/LambdaFunctionDynamoDB Role/LambdaFunctionDynamoDB  is not authorized to perform: dynamodb:GetItem on resource: arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People because no identity-based policy allows the dynamodb:GetItem action",
您需要在政策的一系列許可權中新增「dynamodb:GetItem」。

使用以下內容更新 DynamoDBAccessPolicy.json 檔案:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:DescribeTable",
        "dynamodb:GetItem"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People"
    }
  ]
}
重新部署 Lambda 函數:
dotnet lambda deploy-function LambdaFunctionDynamoDB
再次調用:
dotnet lambda invoke-function LambdaFunctionDynamoDB 
成功!
Amazon Lambda Tools for .NET Core applications (5.4.2)
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet

Payload:
"Alice Andrews lives in MA"
當嘗試授予角色盡可能少的許可權時,Lambda 錯誤訊息非常有用,但是正如您所看到的,您可能需要重複這個過程幾次。

另一種選擇是將滑鼠懸停在您正在使用的 SDK 方法上,中繼資料可能包含有關許可權的有用資訊。並非所有方法中繼資料都包含許可權資訊。
您還應查閱 AWS 服務文檔以獲取有關所需許可權的資訊。

現在,您知道了如何查找您的函數所需的許可權,以及如何向 Lambda 函數以之執行的角色授予正確的許可權。

允許其他服務調用 Lambda 函數

在許多場景下,您需要其他服務來為您調用 Lambda 函數。一些常見場景包括訊息到達佇列、事件到達 Kinesis 串流、變更 S3 中物件/儲存貯體、請求到達 API 閘道。在每種情況下,Lambda 函數都將由另一項 AWS 服務調用。

在上一節中,您學習了如何向 Lambda 函數授予對其他服務執行操作的許可權。在本節中,您將看到如何向其他服務授予調用您的 Lambda 函數的許可權。

如果您使用的是 serverless.* 範本,則可能已經向 API 閘道授予了調用 Lambda 函數所需的許可權。如果您已經部署了此類函數,請轉至「配置」標籤,選擇左側的「許可權」,然後滾動到「基於資源的政策」部分。您將看到允許 API 閘道調用您的 Lambda 函數的政策。此政策由 dotnet lambda deploy-serverless 命令和項目中的 serverless.template 新增。

在下圖中,您可以看到兩個允許 API 閘道調用 Lambda 函數的政策陳述式。
但是您將要研究的範例允許 S3 儲存貯體在您建立或刪除該儲存貯體中的檔時調用您的 Lambda 函數。

建立 S3 儲存貯體

第一步是建立 S3 儲存貯體。

如果您希望自己的儲存貯體位於 us-east-1,可以使用以下命令:
aws s3api create-bucket --bucket my-unique-bucket-name-lambda-course
如果您想自己的儲存貯體位於其他區域,可以使用以下命令:
aws s3api create-bucket --bucket my-unique-bucket-name-lambda-course --create-bucket-configuration LocationConstraint=REGION
有關 LocationConstraint 的有效區域清單,請參見以下連結: https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/create-bucket.html

注意:儲存貯體的名稱必須是唯一的。更多資訊請參見此處

建立 Lambda 函數

有一個 Lambda 函數範本可以幫助您處理 S3 事件。它已經新增了所需的 SDK NuGet 套裝軟體。您仍然需要新增所需的角色許可權並建立基於資源的政策以允許 S3 調用該函數。

從命令列執行:
dotnet new lambda.S3 -n S3EventHandler
切換至 S3EventHandler/src/S3EventHandler 目錄:
cd S3EventHandler/src/S3EventHandler
開啟 Function.cs 檔案,將 FunctionHandler 方法替換為以下內容:
public async Task FunctionHandler(S3Event evnt, ILambdaContext context)
{
    context.Logger.LogInformation($"A S3 event has been received, it contains {evnt.Records.Count} records.");   
    foreach (var s3Event in evnt.Records)
    {
        context.Logger.LogInformation($"Action: {s3Event.EventName}, Bucket: {s3Event.S3.Bucket.Name}, Key: {s3Event.S3.Object.Key}");
       if (!s3Event.EventName.Contains("Delete"))
        {   
            try 
            {
                var response = await this.S3Client.GetObjectMetadataAsync(s3Event.S3.Bucket.Name, s3Event.S3.Object.Key);
                context.Logger.LogInformation( $"The file type is {response.Headers.ContentType}");
            } 
            catch (Exception e) 
            {
                context.Logger.LogError(e.Message);
                context.Logger.LogError($"An exception occurred while retrieving {s3Event.S3.Bucket.Name}/{s3Event.S3.Object.Key}. Exception - ({e.Message})");
            }
        } 
        else 
        {
            context.Logger.LogInformation($"You deleted {s3Event.S3.Bucket.Name}/{s3Event.S3.Object.Key}");
        }
    }
}
當 Lambda 函數收到 S3 事件時,Lambda 函數會將事件詳細資訊記錄到 CloudWatch 中。如果 S3 事件是對已建立物件的回應,則該函數將使用 AWS SDK 調用 S3 以獲取檔案類型,然後記錄詳細資訊。

如果 S3 事件是對已刪除物件的回應,則該函數會將儲存貯體/金鑰名稱記錄到 CloudWatch 中。

部署 Lambda 函數

從命令列執行:
dotnet lambda deploy-function S3EventHandler

接下來,系統將詢問您「選擇為您的程式碼提供 AWS 憑證的 IAM 角色:」,您可能會看到之前建立的角色清單,但清單底部將顯示「**建立新 IAM 角色***」選項,在該選項旁邊輸入該數位。

系統將要求您「輸入新 IAM 角色的名稱:」。輸入「S3EventHandlerRole」。

然後,系統將要求您「選擇要附加到新角色的 IAM 政策並授予許可權」,並顯示政策清單。選擇「AWSLambdaBasicExecutionRole」,它位於清單第 6 位。您需要新增政策來授予對 S3 儲存貯體的存取權限,這樣 GetObjectMetadataAsync(..) 調用才能生效。

授予 Lambda 函數獲取物件中繼資料的許可權

在前面的範例中,您建立了一個僅適用於您正在使用的角色的內聯政策。這次,您將建立任何角色都可以使用的政策。

您將了解如何透過幾種方式做到這一點。
命令列
 
在 S3EventHandler/src/S3EventHandler 資料夾中建立一個名為「S3AccessPolicyForCourseBucket.json」的檔案。

政策如下所示,但資源中包含您的儲存貯體名稱。注意最後的 /*,這意味著 s3:GetObject 適用於儲存貯體中的所有物件:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::my-unique-bucket-name-lambda-course/*"
        }
    ]
}
執行以下命令:
aws iam create-policy --policy-name S3AccessPolicyForCourseBucket --policy-document file://S3AccessPolicyForCourseBucket.json
記下該政策的 ARN。

然後將政策附加到您之前建立的角色。執行以下命令:
aws iam attach-role-policy --role-name S3EventHandlerRole --policy-arn arn:aws:iam::694977046108:policy/S3AccessPolicyForCourseBucket
AWS Console
 
轉至 AWS Console 中的 Lambda 函數。

按一下「配置」標籤、左側的「許可權」,然後按一下角色名稱。
這將開啟一個包含該角色詳細資訊的新頁面。

按一下 新增許可權,然後按一下 附加政策

按一下建立策略

在「服務」部分,在突出顯示的文字方塊中輸入 s3,然後選擇 S3。

在「操作」部分輸入 getobject,然後從清單中選擇 GetObject。

在「資源」部分選擇「特定」,然後按一下新增 ARN

輸入儲存貯體名稱,然後為物件名稱選擇「任意」。
輸入政策名稱,然後按一下「建立政策」

返回您按一下「建立政策」的標籤。請按照以下步驟執行操作:

1.重新載入政策清單

2.在篩檢程式中輸入 S3AccessPolicyForCourseBucket

3.選種政策旁邊的方框

4.按一下附加策略

此時,您有一個 S3 儲存貯體、Lambda 函數以及從 S3 儲存貯體獲取物件中繼資料所需的許可權。

現在是時候將 S3 儲存貯體連接到 Lambda 函數了,這樣建立和刪除事件便會觸發 Lambda 函數。

從 S3 儲存貯體中觸發 Lambda 函數

如您所見,能夠使用 AWS 命令列工具和 UI 控制台真是太好了。在下一步中,您將使用 UI 主控台,因為這對此步驟而言更簡單、更清晰。

開啟 S3 中的儲存貯體清單 https://s3.console.thinkwithwp.com/s3/buckets。

按一下您建立的儲存貯體。
開啟「屬性」標籤。

向下滾動到「事件通知」部分。

按一下建立事件通知

輸入事件通知名稱。

選擇左側的前兩個核取方塊:所有物件建立事件所有物件移除事件

滾動到底部的「目標」部分。

選擇 Lambda 函數作為目標。

在下拉清單中,輸入您之前建立的 Lambda 函數的名稱。

按一下儲存變更

完成後,您將在「事件通知」部分看到此新事件通知。

在 AWS Console 中,轉至您之前建立的 Lambda 函數。

請注意,S3 現在已列為了 Lambda 函數的觸發器。

按一下配置標籤,然後按一下左側的許可權

向下滾動到「基於資源的政策」部分

您將看到一條允許 S3 調用 Lambda 函數的政策語句。
按一下「語句 ID」查看政策語句。

測試一下

此 Lambda 函數不向調用方 (在本例中為 S3) 返回任何內容。

相反,Lambda 函數會記錄到 CloudWatch 中,因此您必須去 CloudWatch 查看您的函數是否正常執行。

在您的電腦上建立要上傳到 S3 的文字檔。

從命令列執行:
aws s3api put-object --bucket my-unique-bucket-name-lambda-course --key Hello.txt --body Hello.txt --content-type "text/plain"
aws s3api delete-object --bucket my-unique-bucket-name-lambda-course --key Hello.txt

現在,在 AWS Console 中轉至您的 Lambda 函數並查看日誌。

依次按一下監控標籤和在 CloudWatch 中查看日誌

您將看到一個日誌串流清單,請選擇最新的日誌串流。
您應該看到顯示 S3 事件的日誌條目和您記錄至 CloudWatch 的文本。
另一種查看日誌的方法是使用適用於 Visual Studio、Visual Studio Code 和 Rider 的 AWS 擴擴充功能。

這三款工具的過程相似,開啟 AWS 擴充功能,按一下 CloudWatch 日誌,然後找到 /aws/lambda/S3EventHandler 的日誌串流/組。然後開啟最近的串流。
另一種查看日誌的方法是使用適用於 Visual Studio、Visual Studio Code 和 Rider 的 AWS 擴擴充功能。

這三款工具的過程相似,開啟 AWS 擴充功能,按一下 CloudWatch 日誌,然後找到 /aws/lambda/S3EventHandler 的日誌串流/組。然後開啟最近的串流。

結語

在這個相對簡短的模組中,您了解了很多內容。有人會說,了解角色和政策是在 AWS 上學習的最重要的內容之一。希望這能為您在與 Lambda 函數相關的主題學習中打下良好的基礎。

以下是關鍵要點:如果您希望自己的 Lambda 函數與其他 AWS 服務互動,則需要向您的函數在其他服務上執行的許可權。

如果您希望其他服務調用您的函數,則需要使用基於資源的政策來授予這些服務存取您的函數的許可權。

知識檢查

您現在已經完成了「模組 4:與其他 AWS 服務搭配使用」。以下測試可讓您檢查到目前為止學習到的內容。

1.若您想讓其他服務調用 Lambda 函數,您需要做什麼?(選擇一項)

a.建立 ACL 文件,向其他服務以之執行的角色授予調用 Lambda 函數的許可權

b.建立基於資源的政策文件,向調用服務授予調用 Lambda 函數的許可權

c.無需執行任何操作,因為 Lambda 信任所有其他 AWS 服務

d.向 Lambda 函數以之執行的角色新增正確的許可權

2.您需要向角色新增什麼才能授予其存取 AWS 服務的許可權?(選擇一項)

a.無需新增任何內容,所有角色都可以存取其他 AWS 服務。

b.基於資源的政策

c.具有必要許可權的政策

d.存取控制清單文件

3.建立與 Lambda 函數以之執行的角色一起使用的客戶管理政策的兩種方法是什麼?(選擇兩項)

a.透過命令列

b.包含在函數的原始程式碼中

c.透過 AWS Console

d.執行函數時將其新增到負載中

答案:1-b、2-c、3-ac

結語

在這個相對簡短的模組中,您了解了很多內容。有人會說,了解角色和政策是在 AWS 上學習的最重要的內容之一。希望這能為您在與 Lambda 函數相關的主題學習中打下良好的基礎。

以下是關鍵要點:如果您希望自己的 Lambda 函數與其他 AWS 服務互動,則需要向您的函數在其他服務上執行的許可權。

如果您希望其他服務調用您的函數,則需要使用基於資源的政策來授予這些服務存取您的函數的許可權。

本頁對您是否有幫助?

單元測試與偵錯