aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.59k stars 3.89k forks source link

(transfer): How to get the subnet ip addresses of a SFTP server hosted in a VPC? #14180

Closed gcaggia closed 1 year ago

gcaggia commented 3 years ago

Description

I created an sftp server and I use the option endpointType: 'VPC'.

The idea was to put the sftp server under a network load balancer allowing us to enhance the security and change the port to connect to the sftp server.

To do that, I attached the sftp server to two different subnets (from two different AZs) belonging to the same VPC.

The problem is once the sftp server is created, it is difficult to get the two IP addresses allocated to the sftp server (one per subnet)

This is what I would like to have and is red in the following image:

image

Use Case

I need these two IP addresses in my case for the network load balancer where I use them in the target group:


const targetGroup = new elb.NetworkTargetGroup(this, 'fcxPrintSftpServerTargetGroup', {
      port: 22,
      vpc: vpc,
      protocol: elb.Protocol.TCP,
      targetType: elb.TargetType.IP,
    });

 // my use case
targetGroup.addTarget(new elbTargets.IpTarget(sftpServerIpSubnet1, 22));
targetGroup.addTarget(new elbTargets.IpTarget(sftpServerIpSubnet2, 22));

Problem: currently it is difficult to get sftpServerIpSubnet1 and sftpServerIpSubnet2.

I tried something like:

sftpServer.endpointDetails.addressAllocationIds

But typescript did not like it because: endpointDetails is type CfnServer.EndpointDetailsProperty | cdk.IResolvable

Proposed Solution

Add the attribute endpointConfiguration to CfnServer sftpServer.endpointConfiguration

And we could have the ip addresses as followed:

const sftpServerIpAddresses = sftpServer.endpointConfiguration.PrivateIPv4Address;
console.log(sftpServerIpAddresses[0]);
console.log(sftpServerIpAddresses[1]);

Feedback: for the naming convention, it is great to follow the AWS console. This is why I suggested endpointConfiguration.PrivateIPv4Address, it matches the screenshot of the AWS console I previously shared.

Other

I also created a stackoverflow question: https://stackoverflow.com/questions/67099895/how-to-get-the-subnet-ip-addresses-of-a-sftp-server-hosted-in-a-vpc-with-aws-cdk

Maybe the answer is simple or maybe we need to use a custom resource for that, as mentioned in issue 11374: https://github.com/aws/aws-cdk/issues/11374

iliapolo commented 3 years ago

@gcaggia Yes this would require both a custom resource and an initial implementation of an L2 construct for CfnServer.

We are unassigning and marking this issue as p2, which means that we are unable to work on this immediately. We use +1s to help prioritize our work, and are happy to revaluate this issue based on community feedback. You can reach out to the cdk.dev community on Slack to solicit support for reprioritization.

gcaggia commented 3 years ago

@iliapolo Thank you for your answer.

I would be so grateful if you could help me with how I can get these IP addresses with a customer resource (I really need that for my current project I am working on)

I tried following this code you share on another post:

import * as cr from '@aws-cdk/custom-resources';
import * as transfer from '@aws-cdk/aws-transfer';

const server = new transfer.CfnServer(...);

const serverDescription = new cr.AwsCustomResource(this, 'ServerDescription', {
  onCreate: {
    action: 'describeServer',
    service: 'Transfer',
    parameters: {
      ServerId: server.attrServerId,
    },
    physicalResourceId: cr.PhysicalResourceId.of(server.attrServerId),
  },
  policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: [server.attrArn] })
});

const endpointId = serverDescription.getResponseField('Server.EndpointDetails.VpcEndpointId');

But maybe it is not possible from Transfer, maybe I need to have a different approach and get the IP from the subnet.

iliapolo commented 3 years ago

@gcaggia It looks like its not possible to do that with a single SDK call. You'll need to write a small lambda that fetches the address allocation id's from the server, and then uses them to query for the addresses.

itsabhisek commented 2 years ago

This looks like something that should be provided from the get go with CDK. Accessing a SFTP server in VPC is only possible via NLB, and to create the NLB in code, the IPs will be required.

github-actions[bot] commented 1 year ago

This issue has not received any attention in 1 year. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

merrycoder commented 5 months ago

I ran into the same issue. Is a solution available meanwhile?

extide commented 19 hours ago

@iliapolo Thank you for your answer.

I would be so grateful if you could help me with how I can get these IP addresses with a customer resource (I really need that for my current project I am working on)

I tried following this code you share on another post:

import * as cr from '@aws-cdk/custom-resources';
import * as transfer from '@aws-cdk/aws-transfer';

const server = new transfer.CfnServer(...);

const serverDescription = new cr.AwsCustomResource(this, 'ServerDescription', {
  onCreate: {
    action: 'describeServer',
    service: 'Transfer',
    parameters: {
      ServerId: server.attrServerId,
    },
    physicalResourceId: cr.PhysicalResourceId.of(server.attrServerId),
  },
  policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: [server.attrArn] })
});

const endpointId = serverDescription.getResponseField('Server.EndpointDetails.VpcEndpointId');

But maybe it is not possible from Transfer, maybe I need to have a different approach and get the IP from the subnet.

You were half-way there -- looks like you can get the DNS name to the server by doing this:

        import * as CR from '@aws-cdk/custom-resources';
        import * as transfer from '@aws-cdk/aws-transfer';

        const server = new transfer.CfnServer(...);

        const serverDescription = new CR.AwsCustomResource(
            this,
            'serverDescription',
            {
                onCreate: {
                    action: 'describeServer',
                    service: 'Transfer',
                    parameters: {
                        ServerId: server.attrServerId
                    },
                    physicalResourceId: CR.PhysicalResourceId.of(server.attrServerId)
                },
                policy: CR.AwsCustomResourcePolicy.fromSdkCalls({ resources: [server.attrArn] })
            }
        );

        const endpointId = serverDescription.getResponseField('Server.EndpointDetails.VpcEndpointId');

        const endpointDescription = new CR.AwsCustomResource(
            this,
            'endpointDescription',
            {
                onCreate: {
                    action: 'describeVpcEndpoints',
                    service: 'Ec2',
                    parameters: {
                        VpcEndpointIds: [endpointId]
                    },
                    physicalResourceId: CR.PhysicalResourceId.of(endpointId)
                },
                policy: CR.AwsCustomResourcePolicy.fromSdkCalls({ resources: ['*'] })
            }
        );

        const endpointDnsName = endpointDescription.getResponseField('VpcEndpoints.0.DnsEntries.0.DnsName');