Elastic Beanstalk環境のSecurity Group設定を検討した

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

西澤です。今回Elastic Beanstalk環境を構築した際に、アプリケーションサーバのSecurity Groupの管理をどのようにすべきか検討したので、まとめておこうと思います。ELBに適用されるSecurity Groupについては、デフォルトに任せておけば良さそうなので、今回の焦点はAuto Scalingで動作するEC2に割り当たるSecurity Groupの話です。

前提

今回検討したEB環境は、デフォルトVPCではなく、カスタムVPC内に構築したアプリケーションを対象とします。

デフォルトでアプリケーションサーバに割り当たるSecurity Group

まずは、suzuki.ryoさんの記事をご欄ください。

アプリケーションサーバに適用されるデフォルトのSecurity Groupでは、

  • 作成されるELBをSourceSecurityGroupとするHTTP(80/tcp)を許可
  • Environmentにて、KeyPair指定をすると、0.0.0.0/0からSSH(22/tcp)を許可

が設定されます。

ebextensionsから変更可能なSecurity Group

ebextensionsからこのデフォルトで設定される値を変更することが可能です。先にご紹介したsuzuki.ryoさんのブログ内にもありますが、Resources:option_settings:の2箇所が設定に影響を及ぼします。実体としては、EBから呼ばれるCloudFormationにより適用される形となっています。

Resources: -> AWSEBSecurityGroup:

こちらは実体はCloudFormationから、Type: AWS::EC2::SecurityGroupとして動作します。yaml形式となりますが、CloudFormationのイメージで自由に追記が可能です。 Outbound通信の制御(SecurityGroupEgress)も追加可能でした。今回検証した結果では、AWSEBLoadBalancerSecurityGroupからのHTTP(80/tcp)のInbound許可は、明示的に記載せずともデフォルトで許可されました。

Resources:
  AWSEBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SecurityGroup settings for EB EC2.
      SecurityGroupIngress:
        - {IpProtocol: "tcp", FromPort: "80", ToPort: "80", SourceSecurityGroupId: {"Ref": "AWSEBLoadBalancerSecurityGroup"}}
        - {IpProtocol: "tcp", FromPort: "80", ToPort: "80", CidrIp: "0.0.0.0/0"}
        - {IpProtocol: "tcp", FromPort: "22", ToPort: "22", CidrIp: "10.0.1.0/24"}
      SecurityGroupEgress:
        - {IpProtocol: "icmp", FromPort: "-1", "ToPort" : "-1", "CidrIp" : "0.0.0.0/0" }
        - {IpProtocol: "tcp", FromPort: "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0" }
        - {IpProtocol: "tcp", FromPort: "443", "ToPort" : "443", "CidrIp" : "0.0.0.0/0" }
        - {IpProtocol: "tcp", FromPort: "53", "ToPort" : "53", "CidrIp" : "0.0.0.0/0" }
        - {IpProtocol: "udp", FromPort: "53", "ToPort" : "53", "CidrIp" : "0.0.0.0/0" }
        - {IpProtocol: "udp", FromPort: "123", "ToPort" : "123", "CidrIp" : "0.0.0.0/0" }

option_settings:

こちらから、デフォルトで許可される「0.0.0.0/0からSSH(22/tcp)」をオーバーライドして制限することができます。しないとダメですね。

EBから呼びだされたCloudFormationテンプレートを確認してみると、前項のType: AWS::EC2::SecurityGroupに追記する形で、Type: "AWS::EC2::SecurityGroupIngress"として1行追加される形で記載されていました。書式が他に無い形ですし、リストで複数渡すこともできないようです。SSHを開放し過ぎるのも不味いので、ちょっと強引に実装されているような印象です。柔軟な変更はできず、書式に従って1行のみ書ける特別なものと考えると良さそうです。

option_settings:
  - namespace:  aws:autoscaling:launchconfiguration
    option_name: SSHSourceRestriction
    value: tcp, 22, 22, 10.0.0.0/24

ebextensionsに指定した結果の例

前述の2種類の設定を組み合わせた形で反映された結果のサンプルが以下となります。これまでの説明を踏まえてご確認ください。

eb_sg_inbound

eb_sg_outbound

Environmentから追加可能なSecurity Group

今回のようにカスタムVPC内にEB環境を構築すると、Server -> EC2 security groups から追加でSecurity Groupを指定することが可能です(デフォルトVPC利用の場合は選択できません)。こちらは、前述のAWSEBSecurityGroupで設定されるものとは別に、追加のSecurity Groupを起動されるアプリケーションサーバ(EC2)に割り当てる形となります。

eb_environment

EB環境のSecurity Group運用を考える

Security Groupはデフォルトの拒否からホワイトリストとして動作するものという点を考慮した上で、整理してみます。

ebextensionsは基本的にアプリケーションの一部としてデプロイする形での運用となりますので、こちらで設定するSecurityGroupでは、アプリケーションに依存している必要最低限の要件のみを記載するのが良さそうです。EnvironmentからSecurity Groupを追加指定しておいて、今後追加・更新される可能性のある設定(運用要件での通信等)はこちらで管理する方が良いのではと思いました。

  • ebextensionsからのSecurity Group設定
    • デフォルト値のSSH許可設定はオーバーライドが必要
    • 変更する為にはApplication Version更新(デプロイ)が必要(※直接Security Groupを変更することも可能ではありますが...)
    • ->->-> 変更される可能性の低い、必要最低限の通信要件のみを管理する
  • EnvironmentからのSecurity Group設定
    • 一度追加指定しておけば、アプリケーションとは独立して管理できる
    • アプリケーションと管理が全く別になる為、再構築やクローンの際にどうするかは別途検討
    • ->->-> 追加・更新される可能性のある通信要件を管理する

今回検討した環境では構築したシステムが安定稼働していたケースだったのですが、別環境への移行や再構築の頻度が高いケースでは逆(Appilcation Versionに全部入れて管理する)の方が良いケースもあると思います。

まとめ

細かい知識不足だったので、整理して動作確認をするのに少し時間がかかりました。一度使い出すととても便利なElastic Beanstalkですが、要件を実現する為に利用できる方法がいくつかあるので、設計・検討が難しく感じました。とりあえずSecurity Groupについては整理できたのでちょっとすっきりです。異なる要件下では違った結論になることもあると思いますので、また改めて考えてみようと思います。

どこかの誰かのお役に立てば嬉しいです。