title: AWS PrivateLink + CloudFormation setup questions from reading the docs
body: <h2>What I'm doing</h2>
  <p>I am trying to do this:</p>
  <blockquote>
  <p>Launch tasks in a private subnet and make sure you have AWS PrivateLink endpoints configured in your VPC, for the services you need (ECR for image pull authentication, S3 for image layers, and AWS Secrets Manager for secrets).</p>
  </blockquote>
  <p>My understanding of this is that AWS services act as a &quot;VPC Endpoint Service&quot; and all that I need to do is set up a &quot;Interface VPC endpoint&quot; to make my service a &quot;service consumer&quot; as described here: <a href="https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-interface.html" rel="nofollow noreferrer">https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-interface.html</a></p>
  <p>I have tried to implement this in CloudFormation, but I have a few questions from reading the documentation.</p>
  <h2>My Questions</h2>
  <h3>Question 1</h3>
  <p>The <a href="https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-interface.html#create-interface-endpoint" rel="nofollow noreferrer">documentation</a> explains how to create the Interface VPC Endpoints, which is great. But it also says: &quot;To turn on private DNS for the interface endpoint, for Enable DNS Name, select the check box.&quot; and &quot;This option is turned on by default&quot;</p>
  <p>But over here: <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpcendpoint.html#cfn-ec2-vpcendpoint-privatednsenabled" rel="nofollow noreferrer">https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpcendpoint.html#cfn-ec2-vpcendpoint-privatednsenabled</a></p>
  <p>It says: &quot;Default: false&quot;. Which is it?</p>
  <h3>Question 2</h3>
  <p>I need to enable 3 ServiceNames. So... do I need to repeat this 3 times? My YAML which repeats the AWS::EC2::VPCEndpoint 3 times is below. Is this really correct? It seems too long / verbose.</p>
  <pre><code>privateVPCEndpoint1:
      Type: AWS::EC2::VPCEndpoint
      Properties:
        ServiceName: !Sub com.amazonaws.${AWS::Region}.ecr.dkr
        PrivateDnsEnabled: True
        # &quot;If this parameter is not specified, we attach a default policy that allows full access to the service.&quot;
        # PolicyDocument:
        SecurityGroupIds:
          - !Ref ECSSecurityGroupDownloadRedisContainer
        SubnetIds:
          - !Ref privateSubnet1
          - !Ref privateSubnet2
        VpcEndpointType: Interface
        VpcId: !Ref VPC
    privateVPCEndpoint2:
      Type: AWS::EC2::VPCEndpoint
      Properties:
        ServiceName: !Sub com.amazonaws.${AWS::Region}.ecr.api
        PrivateDnsEnabled: True
        SecurityGroupIds:
          - !Ref ECSSecurityGroupDownloadRedisContainer
        SubnetIds:
          - !Ref privateSubnet1
          - !Ref privateSubnet2
        VpcEndpointType: Interface
        VpcId: !Ref VPC
    privateVPCEndpoint3:
      Type: AWS::EC2::VPCEndpoint
      Properties:
        ServiceName: !Sub com.amazonaws.${AWS::Region}.ecr.s3
        PrivateDnsEnabled: True
        SecurityGroupIds:
          - !Ref ECSSecurityGroupDownloadRedisContainer
        SubnetIds:
          - !Ref privateSubnet1
          - !Ref privateSubnet2
        VpcEndpointType: Interface
        VpcId: !Ref VPC
  </code></pre>
  <h3>Question 3</h3>
  <blockquote>
  <p>For Security group, select the security groups to associate with the endpoint network interfaces.</p>
  </blockquote>
  <p>Do I use the ECSSecurityGroupDownloadRedisContainer security group which is attached to my ECS Service via NetworkConfiguration / AwsvpcConfiguration / SecurityGroups? If yes, do I need to associate both ECSSecurityGroupDownloadRedisContainer (which allows traffic on 443) and ECSSecurityGroupRedis (which allows traffic on 6379)? I assume the answer to this is yes + only  ECSSecurityGroupDownloadRedisContainer but I don't really know.</p>
  <h3>Question 4</h3>
  <p>Can I somehow disable access to ECS on port 443 after the container has been downloaded? I only need access to 6379 for Redis; anything else seems like a security liability to me.</p>
  <h2>Background: Why I'm Doing This</h2>
  <p>I am trying to create a ECS cluster + Service + Task, but I am getting the error:</p>
  <p><code>(CannotPullContainerError: inspect image has been retried 5 time(s): failed to resolve ref &quot;docker.io/library/redis:latest&quot;: failed to do request: Head https://registry-1.docker.io/v2/library/redis/manifests/latest: dial tcp 34.231.251.252:443: i/o timeout)</code></p>
  <p>Research has pointed me to this post: <a href="https://stackoverflow.com/questions/61265108/aws-ecs-fargate-resourceinitializationerror-unable-to-pull-secrets-or-registry">Aws ecs fargate ResourceInitializationError: unable to pull secrets or registry auth</a></p>
  <p>With this authoritative answer by an AWS employee nathan peck from March of this year: <a href="https://stackoverflow.com/a/66802973">https://stackoverflow.com/a/66802973</a></p>
  <p>They suggest one of three resolutions:</p>
  <ul>
  <li>Launch tasks into a public subnet, with a public IP address, so that they can communicate to ECR and other backing services using an internet gateway</li>
  <li>Launch tasks in a private subnet that has a VPC routing table configured to route outbound traffic via a NAT gateway in a public subnet. This way the NAT gateway can open a connection to ECR on behalf of the task.</li>
  <li>Launch tasks in a private subnet and make sure you have AWS PrivateLink endpoints configured in your VPC, for the services you need (ECR for image pull authentication, S3 for image layers, and AWS Secrets Manager for secrets).</li>
  </ul>
  <p>As you know, redis operates on port 6379, not port 443. My thoughts on these solutions:</p>
  <ul>
  <li>Option 1 is very dangerous! I should NEVER be forced to expose my database instance to the public internet. So that's out.</li>
  <li>Option 2 is what I started to implement, and then I realized that this involved exposing and allowing traffic on port 443 in my subnet + routing table + etc. That seems like an unnecessary security risk when I'm only going to be using port 443 @ container startup.</li>
  <li>Option 3 seems like the right thing to do.</li>
  </ul>
  <p>Thus, my journey.</p>