我正在尝试从AWS Lambda(Java)连接到RDS数据库。
我应该在RDS安全组规则中启用哪个IP地址?
我正在尝试从AWS Lambda(Java)连接到RDS数据库。
我应该在RDS安全组规则中启用哪个IP地址?
您无法通过IP启用此功能。首先,您需要为Lambda函数启用VPC访问权限,在此过程中,您将为其分配安全组。然后,在分配给RDS实例的安全组中,您将启用对Lambda函数指定的安全组的访问权限。
您可以配置Lambda访问您的RDS实例。
您可以通过Lambda管理控制台启用此功能。 选择需要访问RDS实例的Lambda函数,然后转到“配置” - >“高级设置”,并选择您需要访问它的VPC(即您的RDS实例所在的VPC)。
了解更多信息,请访问http://docs.aws.amazon.com/lambda/latest/dg/vpc.html
如果其他人正在寻找更详细的解决方案,或者通过AWS SAM / Cloudformation进行配置的lambda,对我有用的是:
i. 创建一个安全组(SG),允许在您希望连接的特定端口上出站流量(例如:5432或3306。注意,我认为入站规则对lambda没有影响,目前)将该SG应用于您的lambda。
ii. 创建一个允许在相同端口(如5432或3306)上入站流量并引用lambda SG的SG,以便流量仅限于lambda,并在同一端口(5432或3306)上出站。将该SG应用于您的RDS实例。
进一步详细信息:
Lambda SG:
Direction Protocol Port Source
Outbound TCP 5432 ALL
RDS SG.Direction Protocol Port Source
Inbound TCP 5432 Lambda SG
Outbound TCP 5432 ALL
SAM模板.yaml用于配置主要资源,包括:一个RDS集群(此示例中显示了用Aurora Postgres无服务器来最小化运行成本),存储在Secrets Manager中的Postgres主用户密码,一个Lambda函数,将应用于Lambda的SG允许在5432端口上进行出站流量,将应用于RDS集群的SG引用Lambda SG(限制流量到Lambda),我还展示了您可能希望如何使用桌面数据库客户端(例如DBeaver)通过SSH隧道连接到RDS,并通过堡垒机(例如附有EIP的nano EC2实例,以便可以停止并保持所有配置不变)从本地计算机管理RDS。
(请注意,对于生产系统,您可能希望将RDS配置在私有子网中以提高安全性。为简洁起见,在此未介绍子网的配置。另请注意,对于生产系统,作为环境变量传递安全秘密并不是最佳做法,Lambda应该每次解析秘密 - 但由于简洁起见,显示已作为env var传递)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Provisions stack with Aurora Serverless
Parameters:
AppName:
Description: "Application Name"
Type: String
Default: RDS-example-stack
DBClusterName:
Description: "Aurora RDS cluster name"
Type: String
Default: rdsexamplecluster
DatabaseName:
Description: "Aurora RDS database name"
Type: String
Default: examplerdsdbname
DBMasterUserName:
AllowedPattern: "[a-zA-Z0-9_]+"
ConstraintDescription: must be between 1 to 16 alphanumeric characters.
Description: The database admin account user name, between 1 to 16 alphanumeric characters.
MaxLength: '16'
MinLength: '1'
Type: String
Default: aurora_admin_0
Resources:
# lambdas
someLambda:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub '${AWS::StackName}-someLambda'
# Role: !GetAtt ExecutionRole.Arn # if you require a custom execution role and permissions
VpcConfig:
SubnetIds: [subnet-90f79cd8, subnet-9743e6cd, subnet-8bf962ed]
SecurityGroupIds: [!Ref lambdaOutboundSGToRDS]
Handler: index.handler
CodeUri: ./dist/someLambda
Runtime: nodejs14.x
Timeout: 5 # ensure matches your PG/ mySQL connection pool timeout
ReservedConcurrentExecutions: 5
MemorySize: 128
Environment: # optional env vars useful for your DB connection
Variables:
pgDb: !Ref DatabaseName
# dbUser: '{{resolve:secretsmanager:some-stackName-AuroraDBCreds:SecretString:username}}'
# dbPw: '{{resolve:secretsmanager:some-stackName-AuroraDBCreds:SecretString:password}}'
# SGs
lambdaOutboundSGToRDS: # Outbound access for lambda to access Aurora Postgres DB
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${AWS::StackName} access to Aurora PG DB
GroupName: !Sub ${AWS::StackName} lambda to Aurora access
SecurityGroupEgress:
-
CidrIp: '0.0.0.0/0'
Description: lambda to Aurora access over 5432
FromPort: 5432
IpProtocol: TCP
ToPort: 5432
VpcId: vpc-f6c4ea91
RDSSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${AWS::StackName} RDS ingress and egress
SecurityGroupEgress:
-
CidrIp: '0.0.0.0/0'
Description: lambda RDS access over 5432
FromPort: 5432
IpProtocol: TCP
ToPort: 5432
SecurityGroupIngress:
-
SourceSecurityGroupId: !Ref lambdaOutboundSGToRDS # ingress SG for lambda to access RDS
Description: lambda to Aurora access over 5432
FromPort: 5432
IpProtocol: TCP
ToPort: 5432
- # optional
CidrIp: '172.12.34.217/32' # private IP of your EIP/ bastion instance the EIP is assigned to. /32 ie a single IP address
Description: EC2 bastion host providing access to Aurora RDS via SSH tunnel for DBeaver desktop access over 5432
FromPort: 5432
IpProtocol: TCP
ToPort: 5432
VpcId: vpc-f6c4ea91
DBSubnetGroup: # just a logical grouping of subnets that you can apply as a group to your RDS
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: CloudFormation managed DB subnet group.
SubnetIds:
- subnet-80f79cd8
- subnet-8743e6cd
- subnet-9bf962ed
AuroraDBCreds: # provisions a password for the DB master username, which we set in Parameters
Type: AWS::SecretsManager::Secret
Properties:
Name: !Sub ${AWS::StackName}-AuroraDBCreds
Description: RDS database auto-generated user password
GenerateSecretString:
SecretStringTemplate: !Sub '{"username": "${DBMasterUserName}"}'
GenerateStringKey: "password"
PasswordLength: 30
ExcludeCharacters: '"@/\'
Tags:
-
Key: AppName
Value: !Ref AppName
RDSCluster:
Type: AWS::RDS::DBCluster
Properties:
DBClusterIdentifier: !Ref DBClusterName
MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref AuroraDBCreds, ':SecretString:username}}' ]]
MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref AuroraDBCreds, ':SecretString:password}}' ]]
DatabaseName: !Ref DatabaseName
Engine: aurora-postgresql
EngineMode: serverless
EngineVersion: '10' # currently provisions '10.serverless_14' 10.14
EnableHttpEndpoint: true
ScalingConfiguration:
AutoPause: true
MaxCapacity: 2
MinCapacity: 2
SecondsUntilAutoPause: 300 # 5 min
DBSubnetGroupName:
Ref: DBSubnetGroup
VpcSecurityGroupIds:
- !Ref RDSSG
# optional outputs useful for importing into another stack or viewing in the terminal on deploy
Outputs:
StackName:
Description: Aurora Stack Name
Value: !Ref AWS::StackName
Export:
Name: !Sub ${AWS::StackName}-StackName
DatabaseName:
Description: Aurora Database Name
Value: !Ref DatabaseName
Export:
Name: !Sub ${AWS::StackName}-DatabaseName
DatabaseClusterArn:
Description: Aurora Cluster ARN
Value: !Sub arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:${DBClusterName}
Export:
Name: !Sub ${AWS::StackName}-DatabaseClusterArn
DatabaseSecretArn:
Description: Aurora Secret ARN
Value: !Ref AuroraDBCreds
Export:
Name: !Sub ${AWS::StackName}-DatabaseSecretArn
DatabaseClusterID:
Description: Aurora Cluster ID
Value: !Ref RDSCluster
Export:
Name: !Sub ${AWS::StackName}-DatabaseClusterID
AuroraDbURL:
Description: Aurora Database URL
Value: !GetAtt RDSCluster.Endpoint.Address
Export:
Name: !Sub ${AWS::StackName}-DatabaseURL
DatabaseMasterUserName:
Description: Aurora Database User
Value: !Ref DBMasterUserName
Export:
Name: !Sub ${AWS::StackName}-DatabaseMasterUserName
这是我所做的:
我将相同的子网和虚拟私有云(VPC)分配给Lambda服务和RDS服务。现在,我创建了一个NAT网关,并选择了其中一个子网,以便Lambda可以使用该NAT网关与外部世界进行交互。
最后一件事是在附加到RDS及Lambda函数的安全组中添加入站条目。在我的情况下,将DB端口5432列入白名单,同时在源中添加安全组名称。
通过在入站规则中添加条目,安全组本身也被列入白名单。
这对我来说很有效。
推荐的方式仍然是(1)使用VPC和data-api,但是你也可以选择(2)RDS代理 (https://aws.amazon.com/blogs/compute/using-amazon-rds-proxy-with-aws-lambda/),自2020年6月30日起支持MySQL和PostgreSQL两种数据库。
您不需要使用IP。
我假设您的RDS位于VPC的私有子网中。这意味着您的Lambda函数也应该在VPC中,以便与数据库通信。
假设您的RDS凭据存储在Secret Manager中。您可以授予必要的权限,以便Lambda函数可以访问解密Secret。
向数据库添加适当的入站规则。确保您的安全组已正确配置。您还可以使用RDS代理来重用数据库连接,以提高性能。
本文介绍了如何从Lambda函数与RDS进行通信 https://www.freecodecamp.org/news/aws-lambda-rds/