模块 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 服务
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
向表中添加一些项目:
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
cd LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB
dotnet add package AWSSDK.DynamoDBv2
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;}
}
dotnet lambda deploy-function LambdaFunctionDynamoDB
使用以下代码将 Lambda 函数部署至 AWS Lambda:
dotnet lambda deploy-function LambdaFunctionDynamoDB
接下来,系统将询问您“选择为您的代码提供 AWS 凭证的 IAM 角色:”,您可能会看到之前创建的角色列表,但列表底部将显示“**创建新 IAM 角色***”选项,在该选项旁边输入该数字。
系统将要求您“输入新 IAM 角色的名称:”。输入“LambdaFunctionDynamoDBRole”。
然后,系统将要求您“选择要附加到新角色的 IAM Policy 并授予权限”,并显示策略列表。选择“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"
意思就是,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
dotnet lambda deploy-function LambdaFunctionDynamoDB
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",
使用以下内容更新 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"
}
]
}
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"
另一种选择是将鼠标悬停在您正在使用的 SDK 方法上,元数据可能包含有关权限的有用信息。并非所有方法元数据都包含权限信息。
现在,您知道了如何查找您的函数所需的权限,以及如何向 Lambda 函数以之运行的角色授予正确的权限。
允许其他服务调用 Lambda 函数
在上一节中,您学习了如何向 Lambda 函数授予对其他服务执行操作的权限。在本节中,您将看到如何向其他服务授予调用您的 Lambda 函数的权限。
如果您使用的是 serverless.* 模板,则可能已经向 API 网关授予了调用 Lambda 函数所需的权限。如果您已经部署了此类函数,请转至“配置”选项卡,选择左侧的“权限”,然后滚动到“基于资源的策略”部分。您将看到允许 API 网关调用您的 Lambda 函数的策略。此策略由 dotnet lambda deploy-serverless 命令和项目中的 serverless.template 添加。
在下图中,您可以看到两个允许 API 网关调用 Lambda 函数的策略语句。
创建 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
创建 Lambda 函数
从命令行运行:
dotnet new lambda.S3 -n S3EventHandler
cd S3EventHandler/src/S3EventHandler
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}");
}
}
}
如果 S3 事件是对已删除对象的响应,则该函数会将桶/密钥名称记录到 CloudWatch 中。
部署 Lambda 函数
dotnet lambda deploy-function S3EventHandler
接下来,系统将询问您“选择为您的代码提供 AWS 凭证的 IAM 角色:”,您可能会看到之前创建的角色列表,但列表底部将显示“**创建新 IAM 角色***”选项,在该选项旁边输入该数字。
系统将要求您“输入新 IAM 角色的名称:”。输入“S3EventHandlerRole”。
然后,系统将要求您“选择要附加到新角色的 IAM Policy 并授予权限”,并显示策略列表。选择“AWSLambdaBasicExecutionRole”,它位于列表第 6 位。您需要添加策略来授予对 S3 桶的访问权限,这样 GetObjectMetadataAsync(..) 调用才能生效。
授予 Lambda 函数获取对象元数据的权限
您将了解如何通过几种方式做到这一点。
策略如下所示,但资源中包含您的桶名称。注意最后的 /*,这意味着 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
然后将策略附加到您之前创建的角色。运行以下命令:
aws iam attach-role-policy --role-name S3EventHandlerRole --policy-arn arn:aws:iam::694977046108:policy/S3AccessPolicyForCourseBucket
单击“配置”选项卡、左侧的“权限”,然后单击角色名称。
单击 添加权限,然后单击 附加策略。
单击创建策略
在“操作”部分输入 getobject,然后从列表中选择 GetObject。
在“资源”部分选择“特定”,然后单击添加 ARN。
返回您单击“创建策略”的选项卡。请按照以下步骤执行操作:
1.重新加载策略列表
2.在过滤器中输入 S3AccessPolicyForCourseBucket
3.勾选策略旁边的方框
4.单击附加策略
此时,您有一个 S3 桶、Lambda 函数以及从 S3 桶获取对象元数据所需的权限。
现在是时候将 S3 桶连接到 Lambda 函数了,这样创建和删除事件便会触发 Lambda 函数。
从 S3 桶中触发 Lambda 函数
打开 S3 中的桶列表 https://s3.console.thinkwithwp.com/s3/buckets。
单击您创建的桶。
向下滚动到“事件通知”部分。
单击创建事件通知。
输入事件通知名称。
选择左侧的前两个复选框:所有对象创建事件和所有对象移除事件。
滚动到底部的“目标”部分。
选择 Lambda 函数作为目标。
在下拉列表中,输入您之前创建的 Lambda 函数的名称。
单击保存更改。
在 AWS 管理控制台中,转至您之前创建的 Lambda 函数。
请注意,S3 现在已列为了 Lambda 函数的触发器。
单击配置选项卡,然后单击左侧的权限。
您将看到一条允许 S3 调用 Lambda 函数的策略语句。
测试一下
相反,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 管理控制台中转至您的 Lambda 函数并查看日志。
依次单击监控选项卡和在 CloudWatch 中查看日志。
这三款工具的过程相似,打开 AWS 扩展程序,单击 CloudWatch 日志,然后找到 /aws/lambda/S3EventHandler 的日志流/组。然后打开最近的流。
这三款工具的过程相似,打开 AWS 扩展程序,单击 CloudWatch 日志,然后找到 /aws/lambda/S3EventHandler 的日志流/组。然后打开最近的流。
结论
以下是关键要点:如果您希望自己的 Lambda 函数与其他 AWS 服务交互,则需要向您的函数在其他服务上运行的权限。
如果您希望其他服务调用您的函数,则需要使用基于资源的策略来授予这些服务访问您的函数的权限。
知识测验
1.若您想让其他服务调用 Lambda 函数,您需要做什么?(选择一项)
b.创建基于资源的策略文档,向调用服务授予调用 Lambda 函数的权限
c.无需执行任何操作,因为 Lambda 信任所有其他 AWS 服务
d.向 Lambda 函数以之运行的角色添加正确的权限1
2.您需要向角色添加什么才能授予其访问 AWS 服务的权限?(选择一项)
b.基于资源的策略
c.具有必要权限的策略
d.访问控制列表文档
3.创建与 Lambda 函数以之运行的角色一起使用的客户管理策略的两种方法是什么?(选择两项)
a.通过命令行
b.包含在函数的源代码中
c.通过 AWS 管理控制台
d.执行函数时将其添加到负载中
答案:1-b,2-c,3-ac
结论
以下是关键要点:如果您希望自己的 Lambda 函数与其他 AWS 服务交互,则需要向您的函数在其他服务上运行的权限。
如果您希望其他服务调用您的函数,则需要使用基于资源的策略来授予这些服务访问您的函数的权限。