【CloudFormation】別アカウントからのPrivateLink接続を試してみた

2022.02.10

こんにちは、森田です。

この記事では、別アカウントからVPC内のサービスへセキュアにアクセスする方法の1つである
PrivateLink接続について実際に構築し試していきます。

また、構築には、CloudFormationで行っておりますので、実際にお試し可能です。

構成図

以下、構成図となります。CloudFormationでは、Service Provider側のリソースを作成します。

用意するもの

  • AWSアカウント2つ(同じアカウントからでも接続可能です)
  • WEBサーバ構築済みのAMI
  • 以下のCloudFormationテンプレート

CloudFormationテンプレート

AWSTemplateFormatVersion: 
  "2010-09-09"
Description:
  AWS PrivateLink For SaaS

Parameters:
  EC2AMI:
    Type: String
  PJPrefix:
    Type: String
  InstanceType:
    Type: String
  KeyPairName:
    Type: String
  AllowAccountID:
    Type: String

Resources:
  VPC: 
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: "10.0.0.0/16"
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-vpc"
  
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties: 
      AvailabilityZone: "ap-northeast-1a"
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-subnet"
  
  PrivateRouteTable: 
    Type: AWS::EC2::RouteTable
    Properties: 
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-table"
  
  PrivateSubnetTableAssociation: 
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties: 
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateRouteTable
  
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "privatelink"
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: "0.0.0.0/0"
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-ec2"

  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-App"
      ImageId: !Ref EC2AMI
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyPairName
      DisableApiTermination: false
      EbsOptimized: false
      SecurityGroupIds:
        - !Ref SecurityGroup
      SubnetId: !Ref PrivateSubnet

  TargetGroup: 
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties: 
      VpcId: !Ref VPC
      Name: !Sub "${PJPrefix}-tg"
      Protocol: TCP
      Port: 80
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-tg"
      Targets: 
        - Id: !Ref EC2Instance
          Port: 80
      
  NLB: 
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties: 
      Name: !Sub "${PJPrefix}-nlb"
      Tags: 
        - Key: Name
          Value: !Sub "${PJPrefix}-nlb"
      Scheme: "internal"
      LoadBalancerAttributes: 
        - Key: "deletion_protection.enabled"
          Value: false
      Subnets: 
        - !Ref PrivateSubnet
      Type: network

  NLBListener: 
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties: 
      DefaultActions: 
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      LoadBalancerArn: !Ref NLB
      Port: 80
      Protocol: TCP

  VPCEndpoint:
    Type: AWS::EC2::VPCEndpointService
    Properties: 
      AcceptanceRequired: true
      NetworkLoadBalancerArns:
        - !Ref NLB
      
  VPCEndpointPermission:
    Type: AWS::EC2::VPCEndpointServicePermissions
    Properties: 
      AllowedPrincipals: 
        - !Sub "arn:aws:iam::${AllowAccountID}:root"
      ServiceId: !Ref VPCEndpoint

パラメータとして、EC2のAMI IDを渡すように設定しています。
事前にWEBサーバの設定などを済ませて、イメージを作成しておきましょう。
また、事前にエンドポイントに対して、許可するアカウントIDも入力します。

やってみる

1. Service Provider側

まずは、CloudFormationでスタックを作成します。
作成後、VPCエンドポイントサービスが構成されているので、そのサービス名をメモしておきます。

2. 接続する側(Account A)

続いて、別のアカウントでログインを行い、VPCエンドポイントを作成します。
その際に先ほどメモしておいたサービス名を入力し、DNSの非有効化、配置するVPCやサブネット、セキュリティグループの設定などを行います。

3. Service Provider側

Service Provider側でエンドポイント接続の許可が必要ですので、承諾を選択します。
しばらく待つと、ステータスが使用可能になるので、実際に別アカウント内のEC2から動作を確認してみます。

4. 接続する側(Account A)のEC2

接続する側(Account A)のEC2へ接続し、curlでコンソールにあるDNSへリクエストを行います。
すると、正常に動作すれば、以下のようにサービスの結果を得ることができます。

# 別アカウントのEC2へ接続
$ ssh ec2-user@x.x.x.x -i xxx.pem
# curlでDNSへリクエスト
$ curl vpce-hoge1234567890.ap-northeast-1.vpce.amazonaws.com
Hello, PrivateLink!!

まとめ

今回は、CloudFormationでPrivateLinkを試してみましたが、想定したよりも簡単に素早く構成できました。
PrivateLink接続を用いることで、SaaSサービスへセキュアに接続したり、ネットワーク管理を楽にできるなど多くのメリットがありそうですね。

参考