Cloud9 IDE で AWS CLIを実行する際に注意したいネットワーク的制約
はじめに
Cloud9 IDE 検証中に置きた事象とその原因を共有します。 以下まとめです。
- Cloud9 IDE(となるEC2インスタンス)にはグローバルIPが付与される
- そのグローバルIP経由でしか AWS CLIは実行できない
- そのためプライベートサブネット(NATGW経由)からの AWS CLIは失敗する
- 同様に 特定サービスのVPCエンドポイントを置いていると、特定サービスの AWS CLI が失敗する
なにが起きたか
下図のようなシンプルなネットワーク構成で Cloud9 IDEを建てます。
- Cloud9 at PublicSubnet …
direct access
で作成 - Cloud9 at PrivateSubnet …
access via Systems Manager
で作成
※ direct access
は SSH経由で直接 EC2インスタンスへアクセスする構成、
access via Systems Manager
は SSM セッションマネージャ経由でアクセスする構成です
この構成で Cloud9 IDEで AWS APIコールすると、以下のような結果になりました。
VPCエンドポイントが無い状態
パブリックサブネットの Cloud9 IDE は問題無く実行できるが、 プライベートサブネットの Cloud9 IDE で全ての AWS APIコールが失敗する。
なにかVPCエンドポイントを置いたとき
パブリック/プライベートサブネット関係なく、 置いた VPCエンドポイントのサービスの AWS APIコール が失敗する。
なぜ起きたか
Cloud9 IDEで AWS CLIを利用する際には AWS 側で一時クレデンシャル AWS managed temporary credentials(AMTC) が発行され、それを利用しています。
この一時クレデンシャルは利用者の保有する権限と基本的には同等ですが、いくつか制約があります。 その制約で APIコールが失敗していました。
具体的には AMTC ドキュメントの以下部分が原因です。
All supported AWS actions are restricted to the IP address of the environment . This is an AWS security best practice.
Cloud9 IDE(となるEC2インスタンス)にはアクセス方式に関わらず グローバルIPアドレスが付与されます。
引用の the IP address of the environment
はこのグローバルIPアドレスのことです。
AWS APIコールの送信元IPアドレスが このグローバルIPアドレスに制限 されています。
なので、プライベートサブネット上の IDEから APIコールを行った際には、 送信元IPが NATゲートウェイのIP となるので失敗します。
同様に 特定サービスの VPCエンドポイントを置いた場合も、 それ経由の APIコールは 送信元IPが IDEのローカルIP となるので失敗します。
対処法
AMTCを使わない
ローカル端末で行うように、
~/.aws/credentials や ~/.aws/config
を修正して
AWS CLIプロファイルを別のものに設定することでネットワーク的制約は無くなります。
以下記事で実際に別のログインプロファイルを設定しているので参照下さい。
別途IAMユーザーのアクセスキー情報を準備する必要があります。
また 利用者と同等のIAM権限でIDEを利用できる
という
Cloud9のメリットも当然失われます。
(推奨) Cloud9用の VPCを別途作成する
Cloud9 IDEは他システムが稼働しているVPCに置かない ようにする対処方法です。 Cloud9用のVPCとパブリックサブネットを作って、 そこに IDEを建てます。
▼ サクッと Cloud9用VPC/サブネットを作成する CFnテンプレート
AWSTemplateFormatVersion: '2010-09-09' Parameters: VpcCidr: Type: String Default: 192.168.254.0/24 SubnetACidr: Type: String Default: 192.168.254.0/26 SubnetCCidr: Type: String Default: 192.168.254.64/26 SubnetDCidr: Type: String Default: 192.168.254.128/26 Resources: # VPC Vpc: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCidr EnableDnsHostnames: true EnableDnsSupport: true Tags: - Key: Name Value: cloud9-vpc # IGW Igw: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: cloud9-igw IgwAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref Igw VpcId: !Ref Vpc # Subnets SubnetA: Type: AWS::EC2::Subnet Properties: VpcId: !Ref Vpc AvailabilityZone: ap-northeast-1a CidrBlock: !Ref SubnetACidr MapPublicIpOnLaunch: false Tags: - Key: Name Value: cloud9-subnet-a SubnetC: Type: AWS::EC2::Subnet Properties: VpcId: !Ref Vpc AvailabilityZone: ap-northeast-1c CidrBlock: !Ref SubnetCCidr MapPublicIpOnLaunch: false Tags: - Key: Name Value: cloud9-subnet-c SubnetD: Type: AWS::EC2::Subnet Properties: VpcId: !Ref Vpc AvailabilityZone: ap-northeast-1d CidrBlock: !Ref SubnetDCidr MapPublicIpOnLaunch: false Tags: - Key: Name Value: cloud9-subnet-d # Routing RouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref Vpc Tags: - Key: Name Value: cloud9-public-rtb RouteTableAssocA: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref SubnetA RouteTableAssocC: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref SubnetC RouteTableAssocD: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref RouteTable SubnetId: !Ref SubnetD Route: Type: AWS::EC2::Route Properties: RouteTableId: !Ref RouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref Igw
おわりに
以上、Cloud9 IDEで AWS CLIなど実行する際のネットワーク的制約でした。
Cloud9 IDE の接続方法として SSM Session Manager がサポートされていますが、
この意図としては プライベートサブネットでも使えるよ!
ではなくて
インバウンドを閉じた状態でも使えるよ!(ただしパブリックサブネットに限る)
みたいです。
少しでもどなたかのお役に立てば幸いです。