如何解决如何将PUBLIC AWS SFTP服务器转换为使用Terraform托管的VPC
我已经提交了another question,内容相似。但是由于第一个问题不一样,所以有人告诉我要创建一个单独的问题。
我已经在使用terraform创建的现有sftp服务器正在运行。它具有一个PUBLIC端点,我想将该SFTP服务器转换为由IP whitelisting托管的VPC,以保护我的服务器。
Terraform aws_transfer_server
命令目前仅支持endpoint_types,例如PUBLIC或VPC_ENDPOINT。因此,我使用null_resource
执行aws命令以在创建sftp服务器后更新它。我计划使用的地形片段如下:
//Existing command to create a public sftp server
resource "aws_transfer_server" "sftp" {
identity_provider_type = "API_GATEWAY"
url = aws_api_gateway_deployment.api.invoke_url
logging_role = aws_iamrole.log_role.arn
invocation_role = aws_iamrole.api_exec_role.arn
}
resource "aws_vpc_endpoint" "transfer" {
vpc_id = var.vpc_id
service_name = "com.amazonaws.${var.aws_region}.transfer.server"
vpc_endpoint_type = "Interface"
subnet_ids = var.subnet_ids
security_group_ids = [
aws_security_group.sg.id
]
tags = {
Name = "${var.application}-${var.environment}-vpce"
}
}
resource "null_resource" "update_sftp_server" {
provisioner "local-exec" {
command = <<EOF
aws transfer update-server --server-id ${aws_transfer_server.sftp.id} --endpoint-type VPC --endpoint-details SubnetIds="${join("\",\"",var.subnet_ids)}",AddressAllocationIds="${join("\",toset(aws_eip.nlb.*.id))}",VpcId="${var.vpc_id}"
EOF
}
depends_on = [aws_transfer_server.sftp,aws_vpc_endpoint.transfer]
}
null_resource
执行以下aws命令
aws transfer update-server --server-id s-## --endpoint-type VPC --endpoint-details SubnetIds="subnet-##","subnet-##",AddressAllocationIds="eipalloc-##","eipalloc-##",VpcId="vpc-##"
这将引发以下异常:
exit status 254. Output:
An error occurred (InvalidRequestException) when calling the UpdateServer operation: Cannot specify AddressAllocationids when updating server to EndpointType: VPC
我看到,如果我从aws命令中删除了AddressAllocationIds="${join("\",toset(aws_eip.nlb.*.id))}"
,它就可以工作。但是从子网到弹性IP的可用区映射不会发生,如下所示:
将这个PUBLIC sftp服务器转换为VPC Hosted之后,我验证了一段时间后可以运行该命令以单独包括AddressAllocationIds。但是,如果我创建了另一个null_resource
并尝试运行该命令,它将给我同样的错误。有人可以帮助我实现这一目标吗?
我的环境详细信息如下:
Terraform v0.12.28
provider.aws v3.0.0
provider.null v2.1.2
aws-cli/2.0.33 Python/3.7.7 Windows/10 botocore/2.0.0dev37
解决方法
我曾与AWS Support交流过,他们建议创建一个lambda函数来执行此操作,因为此时无法使用单个aws cli命令来执行此操作。
Python中的Lambda函数已压缩并命名为update_sftp_to_vpc
import json
import boto3
import time
def isNullOrWhiteSpace(str=None):
return not str or str.isspace()
def isEmptyList(lst=[]):
return not lst
def lambda_handler(event,context):
transfer_client = boto3.client('transfer')
subnetIds = event['subnetIds']
allocationIds = event['allocationIds']
vpcId = event['vpcId']
serverId = event['serverId']
if(isEmptyList(subnetIds) or isEmptyList(allocationIds) or isNullOrWhiteSpace(vpcId) or isNullOrWhiteSpace(serverId)):
return {
'statusCode': 400,'body': json.dumps('subnetIds or allocationIds or vpcId or serverId is empty')
}
else:
print(
f"Get the server details of server: {serverId} to confirm if the Server is already VPC and AddressAllocationIds exist")
serverDetails = transfer_client.describe_server(ServerId=serverId)
endpointType = serverDetails['Server']['EndpointType']
if(endpointType.upper() == 'VPC'):
existingAllocationIds = serverDetails['Server']['EndpointDetails']['AddressAllocationIds']
if(allocationIds == existingAllocationIds):
return {
'statusCode': 200,'body': json.dumps(f"Server: {serverId} is already of type {endpointType} and with allocationIds: {existingAllocationIds}")
}
print(f"Make sure that the server: {serverId} is stopped")
transfer_client.stop_server(ServerId=serverId)
print(
f"Get the server details of server: {serverId} and wait until the server is offline")
serverDetails = transfer_client.describe_server(ServerId=serverId)
while True:
serverState = serverDetails['Server']['State']
if(serverState.upper() == 'OFFLINE'):
break
print(
f"Server: {serverId} state is {serverState}. Sleeping for 10 seconds until it is OFFLINE")
time.sleep(10)
serverDetails = transfer_client.describe_server(ServerId=serverId)
endpointType = serverDetails['Server']['EndpointType']
if(endpointType.upper() != 'VPC'):
print(
f"Update the server: {serverId} to a VPC Hosted without AllocationIds")
transfer_client.update_server(
EndpointDetails={
'SubnetIds': subnetIds,'VpcId': vpcId
},EndpointType='VPC',ServerId=serverId
)
print(
f"Get the server: {serverId} details and wait until the server is now VPC Hosted")
serverDetails = transfer_client.describe_server(ServerId=serverId)
while True:
endpointType = serverDetails['Server']['EndpointType']
if(endpointType.upper() == 'VPC'):
break
print(
f"Server: {serverId} state is {serverDetails['Server']['EndpointType']}. Sleeping for 10 seconds until it is VPC")
time.sleep(10)
serverDetails = transfer_client.describe_server(ServerId=serverId)
print(f"Get server: {serverId} details again for vpc endpoint details")
serverDetails = transfer_client.describe_server(ServerId=serverId)
vpc_client = boto3.client('ec2')
vpcEndpointId = serverDetails['Server']['EndpointDetails']['VpcEndpointId']
vpcEndpointDetails = vpc_client.describe_vpc_endpoints(
VpcEndpointIds=[vpcEndpointId],Filters=[
{
'Name': 'vpc-endpoint-id','Values': [vpcEndpointId]
},])
while True:
currentVpcState = vpcEndpointDetails['VpcEndpoints'][0]['State']
if(currentVpcState.lower() == 'available'):
break
print(
f"VpcEndpointId: {vpcEndpointId} state is {currentVpcState}. Sleeping for 10 seconds until it is Available")
time.sleep(10)
vpcEndpointDetails = vpc_client.describe_vpc_endpoints(
VpcEndpointIds=[vpcEndpointId],Filters=[
{
'Name': 'vpc-endpoint-id','Values': [vpcEndpointId]
},])
print(f"Update the server: {serverId} again with AddressAllocationIds")
transfer_client.update_server(
EndpointDetails={
'AddressAllocationIds': allocationIds,'SubnetIds': subnetIds,'VpcId': vpcId
},ServerId=serverId
)
print(f"Start the server: {serverId}")
transfer_client.start_server(ServerId=serverId)
return {
'statusCode': 200,'body': json.dumps(f"Sftp server {serverId} is converted to use the VpcId: {vpcId}")
}
然后我要做的就是从我的terraform中调用如下的lambda函数。
resource "aws_lambda_function" "update_sftp_to_vpc" {
function_name = "update-sftp-to-vpc"
description = "Update sftp server to vpc hosted for IP Whitelisting"
role = alks_iamrole.update_server_lambda.arn
runtime = "python3.8"
handler = "lambda_function.lambda_handler"
timeout = "180" //Set to 3 mins. It may need to be revisited if the sftp server takes more time to stop
filename = "update_sftp_to_vpc.zip"
source_code_hash = filebase64sha256("update_sftp_to_vpc.zip")
}
data "aws_lambda_invocation" "update_public_sftp_server_to_vpc" {
function_name = aws_lambda_function.update_sftp_to_vpc.function_name
input = <<JSON
{
"serverId":"${aws_transfer_server.sftp.id}","vpcId":"${var.vpc_id}","subnetIds":${format("[\"%s\"]",join("\",\"",var.subnet_ids))},"allocationIds":${format("[\"%s\"]",toset(aws_eip.nlb.*.id)))}
}
JSON
depends_on = [aws_transfer_server.sftp,aws_lambda_function.update_sftp_to_vpc]
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。