1. はじめに

今回は、AWS Systems Manager の Session Manager を利用して、踏み台サーバー(Bastion Host)の代替手段を構築する方法を紹介します。

Session Manager を活用することで、従来の踏み台サーバーに比べてセキュリティや運用性が向上します。たとえば、SSH鍵の管理や開放ポートの運用から解放され、よりシンプルかつセキュアなアクセス環境を実現できます。

2. Session Managerとは

AWS Session Managerは、AWS System Manager の機能の1つで、EC2インスタンスやオンプレミスサーバーに対して、安全にサーバーにアクセス可能にするサービスです。

2.1 Session Managerを利用するメリット

  • ポートを開く必要がない・鍵管理不要
    • 従来の踏み台サーバーには、sshの22番ポートを開く必要がありますが、AWS Session Managerを利用すれば、ポートを開く必要がなくセキュアに踏み台サーバーを運用することが可能になります。また、sshキーの管理が不要になります。
  • ポート転送
    • EC2インスタンスで動いているアプリケーションに対して、ローカルPCのローカルポートからアクセスできるようになります。また、ローカルPCからEC2インスタンスを踏み台にして、プライベートサブネットに配置されているRDSなどのデータベースにアクセス可能になります。

3. 実際の構成図

構成図

4. AWS Session Managerで踏み台サーバー構築する

4.1. VPCを作成する

VPC:
  Type: AWS::EC2::VPC
  Properties:
    CidrBlock: 192.168.0.0/20
    EnableDnsSupport: true
    EnableDnsHostnames: true
    Tags:
      - Key: Name
        Value: 'vpc'

4.2. プライベートサブネットを作成する

PrivateSubnetAZ1:
  Type: AWS::EC2::Subnet
  Properties:
    VpcId: !Ref VPC
    AvailabilityZone: !Select [0, !GetAZs '']
    CidrBlock: 192.168.0.0/24
    MapPublicIpOnLaunch: false
    Tags:
      - Key: Name
        Value: 'private-subnet-az1'

PrivateSubnetAZ2:
  Type: AWS::EC2::Subnet
  Properties:
    VpcId: !Ref VPC
    AvailabilityZone: !Select [2, !GetAZs '']
    CidrBlock: 192.168.1.0/24
    MapPublicIpOnLaunch: false
    Tags:
      - Key: Name
        Value: 'private-subnet-az2'

4.3. データベースを構築する

RdsDbCluster:
  Type: 'AWS::RDS::DBCluster'
  Properties:
    AvailabilityZones:
      - !Select [0, !GetAZs '']
      - !Select [2, !GetAZs '']
    BackupRetentionPeriod: 7
    DBClusterIdentifier: !Sub '${ProjectName}-database'
    DBClusterParameterGroupName: !Sub '${ProjectName}-aurora-parameter-group'
    DatabaseName: gym_db
    DBSubnetGroupName: !Sub '${ProjectName}-aurora-subnet-group'
    Engine: 'aurora-mysql'
    Port: 3306
    MasterUsername: 'admin_user'
    MasterUserPassword: "DBのパスワード"
    PreferredBackupWindow: '17:20-17:50'
    PreferredMaintenanceWindow: 'sun:15:00-sun:16:00'
    VpcSecurityGroupIds:
      - !ImportValue SgDbSecurityGroup
    StorageEncrypted: true
    EnableIAMDatabaseAuthentication: false
    # 通常のAuroraかAurora Serverlessか選択可能
    EngineMode: 'provisioned'
    DeletionProtection: false
    EnableHttpEndpoint: false

AuroraSubnetGroup:
  Type: AWS::RDS::DBSubnetGroup
  Properties:
    DBSubnetGroupDescription: 'subnet group'
    DBSubnetGroupName: 'aurora-subnet-group'
    SubnetIds:
      - !Ref PrivateSubnetAZ1
      - !Ref PrivateSubnetAZ2

AuroraClusterParameterGroup:
  Type: AWS::RDS::DBClusterParameterGroup
  Properties:
    Description: Aurora MySQL 8.0 cluster parameter group
    DBClusterParameterGroupName: 'aurora-parameter-group'
    Family: aurora-mysql8.0
    Parameters:
      time_zone: Asia/Tokyo
      character_set_database: utf8mb4
    Tags:
      - Key: Name
        Value: 'aurora-cluster-param-group'

DbInstance:
  Type: AWS::RDS::DBInstance
  Properties:
    AllowMajorVersionUpgrade: false
    # DBインスタンスの変更を即時反映させるかメンテナンスウィンドウ時に反映させるか
    ApplyImmediately: true
    AutoMinorVersionUpgrade: false
    # 自動バックアップの保持期間
    BackupRetentionPeriod: 0
    DBClusterIdentifier: !Ref RdsDbCluster
    DBInstanceClass: db.t3.medium
    DBInstanceIdentifier: 'db-instance'
    DBSubnetGroupName: 'aurora-subnet-group'
    DeleteAutomatedBackups: true
    Engine: aurora-mysql
    PreferredMaintenanceWindow: 'sun:17:00-sun:17:30'
    PubliclyAccessible: false

4.4. EC2を作成する

BastionInstance:
  Type: AWS::EC2::Instance
  Properties:
    AvailabilityZone: !Select [0, !GetAZs '']
    DisableApiTermination: false
    IamInstanceProfile: !Ref BastionInstanceProfile
    ImageId: ami-07b0c09aab6e66ee9
    InstanceType: t2.small
    Monitoring: true
    SecurityGroupIds: 
      - !Ref BastionSecurityGroup
    SubnetId: !Ref PrivateSubnetAZ1
    Tags: 
      - Key: Name
        Value: 'bastion-instance'

BastionInstanceProfile: 
  Type: "AWS::IAM::InstanceProfile"
  Properties: 
    Path: "/"
    Roles: 
      - !Ref SessionManagerRole

4.5. VPCエンドポイント

SsmEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm'
    VpcId: !Ref VPC
    VpcEndpointType: Interface
    SubnetIds:
      - !Ref PrivateSubnetAZ1
      - !Ref PrivateSubnetAZ2
    PrivateDnsEnabled: true
    SecurityGroupIds:
      - !Ref SsmVpcEndpointSg
    Tags:
      - Key: Name
        Value: 'logs-vpc-endpoint'

SsmMeessagesEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssmmessages'
    VpcId: !Ref VPC
    VpcEndpointType: Interface
    SubnetIds:
      - !Ref PrivateSubnetAZ1
      - !Ref PrivateSubnetAZ2
    PrivateDnsEnabled: true
    SecurityGroupIds:
      - !Ref SsmVpcEndpointSg
    Tags:
      - Key: Name
        Value: 'logs-vpc-endpoint'

4.6. IAM

Resources:
  SessionManagerRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

Outputs:
  SessionManagerRole:
    Value: !Ref SessionManagerRole
    Export:
      Name: SessionManagerRole

4.8. セキュリティグループ

BastionSecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: "Security group for Bastion host using Session Manager"
    VpcId: !Ref VPC
    SecurityGroupEgress:
      - IpProtocol: tcp
        FromPort: 443
        ToPort: 443
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: 3306
        ToPort: 3306
        CidrIp: 0.0.0.0/0

SsmVpcEndpointSg:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: "Allow SSM traffic"
    VpcId: !Ref VPC
    SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 443
        ToPort: 443
        CidrIp: 0.0.0.0/0

4.9. SSMプラグインをローカルPCにインストールする

以下のページを参考にSSMプラグインをPCにインストールする。

AWS CLI 用の Session Manager プラグインをインストールする

4.10. ssm start

aws ssm start-session \
  --target i-xxxxxxxxxxxxxxxxx \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters '{
      "host":["<aurora-endpoint>"],
      "portNumber":["3306"],
      "localPortNumber":["13306"]
  }'

Session Managerとの通信に成功すれば、Auroraに接続可能になります。 お使いのデータベースクライアントから接続お願いいたします。

※ データベースクライアントは事前にインストールお願いします。 ※ aws cliのインストール、設定は事前にお願いします。

6. よくあるトラブルとその解決策

6.1 AmazonSSMServiceRolePolicy

AmazonSSMServiceRolePolicy は、AWSが提供するマネージドポリシーです。このポリシーは、AWS Systems Manager を使うためにEC2インスタンスにアタッチする必要があり、このポリシーがなければ、EC2とAWS Systems Managerの連携を行うことができません。

6.2 SSM エージェントがEC2にインストールされていない

EC2インスタンスにSSMエージェントがインストールされていなかれば、ローカルPCからSession Managerを利用してアクセスすることはできません。

※ Amazon Linux2やAmazon Linux2023を利用している場合デフォルトでインストールされています。

7. まとめ

AWS Session Managerを利用するとセキュアに、踏み台サーバーを運用することができたり、煩雑な鍵管理から開放されます。

AWS上で踏み台サーバーを作成する際は、導入を検討してみるのも良いかもしれません。

8. 参考サイト

AWS Systems Manager Session Manager