GitLab CIでAWS Systems Managerを使用したEC2インスタンスへのセキュアなSSH,SCP

# はじめに
**AWS Systems Managerを使用する経緯**
[GitLab.com](https://gitlab.com) が提供する GitLab Runner はIPアドレスが固定されていない為、GitLab CIからEC2インスタンスにアクセスする際はSSHのインバウンドポートをフルオープンで運用していました。
> IP range
> For outgoing connections from CI/CD runners, we are not providing static IP addresses. All GitLab.com shared runners are deployed into Google Cloud Platform (GCP). Any IP-based firewall can be configured by looking up all IP address ranges or CIDR blocks for GCP.
> https://docs.gitlab.com/ee/user/gitlab_com/#ip-range


ただし、セキュリティ上どこからでもログイン出来てしまう状況は良く無いです。

そこで、AWS Systems Manager(SSM)のセッションマネージャを利用してセキュアにログインするフローを導入したので、その設定方法をご紹介します。

## 従来ログインとSSM経由ログインの比較
- SSHキーが不要
- セキュリティグループでSSHポートの開放が不要
- プライベートサブネットでも踏み台なしでアクセス可能
- IAMによるアクセス制御が可能
- ログインログ、イベントログが取得可能（S3、Cloud Watch 等との連携）


# 1. EC2インスタンスのセットアップ
## IAMロールの設定
セッションマネージャから接続を許可するIAMロールをEC2インスタンスに設定します。
![スクリーンショット 2022-03-09 0.39.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121942/b48a407e-160f-baab-6d7e-9a15ab9c07ee.png)

「AmazonSSMManagedInstanceCore」の許可ポリシーでIAMロールを作成します。
![スクリーンショット 2022-03-09 0.49.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121942/35e0e882-caae-8cba-0d7a-07303113f414.png)

Systems Manager > フリートマネージャーのノードIDに対象EC2インスタンスが表示されていればOK。
![スクリーンショット 2022-03-17 13.40.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121942/15642a4f-4998-ce45-7500-c9186b32ab44.png)

## SSM Agentのインストール
SSM Agentは、以下の Amazon Machine Images (AMIs) にデフォルトでプリインストールされています。
- Amazon Linux
- Amazon Linux 2
- Amazon Linux 2 ECS に最適化されたベース AMIs
- SUSE Linux Enterprise Server(SLES) 12 と 15
- Ubuntu Server 16.04、18.04 および 20.04

その他の Linux SSM Agent で作成された EC2 インスタンスには、AMIsを手動でインストールする必要があります。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ssm-agent.html

# 2. IAMユーザーのセットアップ
IAMコンソール https://console.aws.amazon.com/iam/ を開き、以下2つのポリシーを作成しIAMユーザーに付与します。

## ポリシー1: セッションマネージャ経由でのSSH接続を許可
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ssm:StartSession",
            "Resource": [
                "arn:aws:ec2:region:account-id:instance/instance-id",
                "arn:aws:ssm:*:*:document/AWS-StartSSHSession"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:TerminateSession",
                "ssm:ResumeSession"
            ],
            "Resource": [
                "arn:aws:ssm:*:*:session/${aws:username}-*"
            ]
        }
    ]
}
```
`region`, `account-id`, `instance-id` は環境に応じて書き換える必要があります。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/getting-started-restrict-access-examples.html

## ポリシー2: Run Commandの実行許可
```json
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "ssm:SendCommand"
         ],
         "Resource":[
            "arn:aws:ssm:*:*:document/*"
         ]
      },
      {
         "Effect":"Allow",
         "Action":[
            "ssm:SendCommand"
         ],
         "Resource":[
            "arn:aws:ec2:region:account-id:instance/instance-id"
         ]
      }
   ]
}

```
`region`, `account-id`, `instance-id` は環境に応じて書き換える必要があります。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-rc-setting-up.html

## IAMユーザーの作成
上記2つのポリシーを付与したユーザーを「認証情報タイプ: アクセスキー - プログラムによるアクセス」で作成し`アクセスキーID`, `シークレットアクセスキー`を手元に控えます。（GitLab CIの設定で使用）

# 3. GitLab CIの設定
## Variablesの登録
GitLabプロジェクト管理画面のSettings > CI/CD > Variablesに以下の環境変数を設定します。

| Type | Key | Value | Masked |
|:-----------------|:-----------------|:------------------|:------------------|
| Variable | AWS_ACCESS_KEY_ID | 上記で取得したアクセスキーID | true |
| Variable | AWS_SECRET_ACCESS_KEY | 上記で取得したシークレットアクセスキー  | true |
| File | EC2_SERVER_PEM  | EC2インスタンスのpemファイル | |

![スクリーンショット 2022-03-17 14.25.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121942/5f0796b4-713b-3475-69f6-21292bbdf7ed.png)

## .gitlab-ci.ymlの作成
```yaml:.gitlab-ci.yml
ssm_test:
  stage: build
  image: python:3.9-slim
  before_script:
    - apt update && apt install -y --no-install-recommends curl ssh openssh-client openssh-server
    - pip install awscli
    - curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o "session-manager-plugin.deb"
    - dpkg -i session-manager-plugin.deb
    - chmod 400 $EC2_SERVER_PEM
    - mkdir -p ~/.ssh/ && echo -e "Host *\n\tStrictHostKeyChecking no\nhost i-* mi-*\n\tProxyCommand sh -c \"aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'\"\n\n" >> ~/.ssh/config
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
    - aws configure set region region
  script:
    - ssh -i $EC2_SERVER_PEM ec2-user@instance-id "実行コマンド"
    - scp -i $EC2_SERVER_PEM コピー元パス ec2-user@instance-id:保存先パス
```
`region`, `instance-id` は環境に応じて書き換える必要があります。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html

---

以上で全ての設定が完了です :tada: :tada: 
AWS Systems Manager セッションマネージャ を利用して、セキュアにログインを行いましょう！