Linux EC2インスタンスをAWS Managed Microsoft ADへシームレスに参加させる

Linux EC2インスタンスをAWS Managed Microsoft ADに参加させてIDの統合管理をしている環境があるのですが、今までインスタンスが増える度に手動でAD参加コマンド実行、パスワード入力という手順を実施してインスタンスのデプロイに非常に時間がかかっていました。加えてEC2 AutoScalingの検討しておりこのパスワード入力の壁越えなきゃなーと調べていたら、今年に入りシームレスなAD参加がサポートされていました！

[Amazon EC2 for Linux インスタンスを AWS Directory Service にシームレスに参加させる](https://aws.amazon.com/jp/about-aws/whats-new/2020/08/seamlessly-join-amazon-ec2-for-linux-instance-to-aws-directory-service/)

ということでLinuxインスタンスデプロイ時にAD参加させる方法を検証してみました。
ちなみに、冒頭で触れた今までのAD参加方法はこちら↓↓
[Linux インスタンスを手動で結合する](https://docs.aws.amazon.com/ja_jp/directoryservice/latest/admin-guide/join_linux_instance.html)

今回検証した手順はこちら↓↓
[Linux EC2インスタンスをシームレスに参加 AWS Managed Microsoft AD ディレクトリ](https://docs.aws.amazon.com/ja_jp/directoryservice/latest/admin-guide/seamlessly_join_linux_instance.html)

# 前提条件

まず2020/11/17時点でサポートされているディストリビューション、バージョンは以下となります。

- Amazon Linux AMI 2018.03.0
- Amazon Linux 2 (64 ビット x86)
- Red Hat Enterprise Linux 8 (HVM) (64 ビット x86)
- Ubuntu Server 18.04 LTS & Ubuntu Server 16.04 LTS
- CentOS 7 x86-64
- SUSE Linux Enterprise Server 15 SP1

Noteに
"Distributions prior to Ubuntu 14 and Red Hat Enterprise Linux 7 do not support the seamless domain join feature."
とありましたので、RHEL7はOKと判断しRHEL7で検証しました。

また、対象インスタンスにはAWS Systems Manager (SSM Agent) バージョン 2.3.1644.0 以上が必要となっています。

ということで、

# 検証環境

- Region: Tokyo
- DirectoryService: AWS Managed Microsoft AD Standard ※作成済み
- AD参加するインスタンス: RedHat Enterprise Linux 7.9
- ADに接続して操作するインスタンス: WindowsServer 2019 ※作成済み

![environment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152958/e99615cf-66be-71b1-2ec0-307a95212c62.png)

# では、検証

AWS Managed Microsoft ADへRHEL7.9インスタンスを起動時に参加させます。
まずはドメインユーザーの作成から。

## AD参加用ドメインユーザーの作成

LinuxインスタンスをAD参加させるため、コンピュータアカウントの作成権限をもつドメインユーザーをサービスアカウントとして設定します。
今回の構成で言うと、AD参加済みのWindowsServer 2019にて、"Active Directory ドメインサービス"を開いて(別のユーザーとして実行からMicrosoft ADのAdminユーザーで接続)ユーザを新規作成しておきました。

![ユーザー追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152958/883c83fe-4242-97df-cdaa-0417479c20f7.png)

次に作成したドメインユーザーに対し権限を付与します。AD参加させるためだけに使用するものとなりますので、できる限り最小限の権限をもたせる形にしたい、ということで下記の通りPowerShellコマンドが用意されていました。1行目の```$AccountName```には先程作成したドメインユーザー名を入力します。

```powershell
$AccountName = 'awsSeamlessDomain'
# DO NOT modify anything below this comment.
# Getting Active Directory information.
Import-Module 'ActiveDirectory'
$Domain = Get-ADDomain -ErrorAction Stop
$BaseDn = $Domain.DistinguishedName
$ComputersContainer = $Domain.ComputersContainer
$SchemaNamingContext = Get-ADRootDSE | Select-Object -ExpandProperty 'schemaNamingContext'
[System.GUID]$ServicePrincipalNameGuid = (Get-ADObject -SearchBase $SchemaNamingContext -Filter { lDAPDisplayName -eq 'Computer' } -Properties 'schemaIDGUID').schemaIDGUID
# Getting Service account Information.
$AccountProperties = Get-ADUser -Identity $AccountName
$AccountSid = New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' $AccountProperties.SID.Value
# Getting ACL settings for the Computers container.
$ObjectAcl = Get-ACL -Path "AD:\$ComputersContainer" 
# Setting ACL allowing the service account the ability to create child computer objects in the Computers container.
$AddAccessRule = New-Object -TypeName 'System.DirectoryServices.ActiveDirectoryAccessRule' $AccountSid, 'CreateChild', 'Allow', $ServicePrincipalNameGUID, 'All'
$ObjectAcl.AddAccessRule($AddAccessRule)
Set-ACL -AclObject $ObjectAcl -Path "AD:\$ComputersContainer"
```

上記コマンドをWindowsServer 2019で実行し、**awsSeamlessDomain**を必要最小限の権限を持ったサービスアカウントとして設定しました。

## Secrets Managerにサービスアカウント情報を保存

インスタンス起動時のドメイン参加において、先程作成したサービスアカウントを利用するため、Secrets Managerに情報を保存しておきます。
Secrets Managerのサービスコンソールに遷移後、**Store a new secret**をクリックし、下図の通り設定しました。

1. **Other type of secrets**を選択し、key/valueにサービスアカウント名とパスワードを指定します。 
![secretmanager01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152958/411c164a-d344-4fb4-cff0-388d45cfa111.png)

2. Secret nameを指定します。
![secretmanager.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152958/fef3f0ac-af55-75ac-c1bd-439217f0be9b.png)

3. Configure rotationでは**Disable automatic rotation**を指定します。

4. 設定を確認して保存すると、新しいシークレットが追加されます。Secret ARNはIAMポリシー設定時に使いますので、控えておきます。

## IAMロールの作成

AD参加するインスタンスに付与するIAMロールを作成します。
対象IAMロールにはAWS管理ポリシー×2、カスタマー管理ポリシー×1をアタッチしますので、先にカスタマー管理ポリシーを作成しておきます。
手順は省略しますが、ポリシー名を**SM-Secret-Linux-DJ-<ディレクトリid>-Read**とし、以下のポリシードキュメントで作成しました。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "secretsmanager:DescribeSecret"
            ],
            "Resource": [
                "<作成したSecretのARN>"
            ]
        }
    ]
}
```

続いてIAMロールは**Select type of trusted entity**で**EC2**を選択し、ポリシーの選択で下記３つの管理ポリシーにチェックを入れます。

- AmazonSSMManagedInstanceCore
- AmazonSSMDirectoryServiceAccess
- SM-Secret-Linux-DJ-<ディレクトリid>-Read ※先程作成したカスタマー管理ポリシー

ロール名は**LinuxEC2DomainJoin**とし、IAMロールを作成します。

## Linux EC2インスタンスをADに参加させる

ここまででLinux EC2インスタンスを新規起動時にAD参加させるための準備が整いました！
インスタンスを起動し、AD参加できていることを実際に確認してみます。

- EC2コンソールから**Launch Instances**をクリックします。
- **Step 1: Choose an Amazon Machine Image (AMI)**では、起動するLinuxインスタンスAMIをします。今回はCommunity AMIsからRHEL7.9を選択しました。
- **Step 2: Choose an Instance Type**で任意のインスタンスタイプを選択します。
- **Step 3: Configure Instance Details**はポイントとなるステップです。VPCなどは各環境に合わせて指定しますが、本ステップでは参加するAD、IAMロール、およびSSM AgentをインストールするためのUserDataを指定します。
    - Domain join directory: 作成済みのAWS Managed Microsoft AD Standardドメイン
    - IAM role: LinuxEC2DomainJoin
    - User data: 以下のスクリプトを指定

```bash
#!/bin/bash -xe
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
yum install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm
systemctl enable amazon-ssm-agent
systemctl start amazon-ssm-agent
systemctl status amazon-ssm-agent
```   

- **Step 4〜6**については環境に合わせて設定します。
- **Step 7: Review Instance Launch**で設定内容を確認し、**Launch**をクリックします。

新規Linux EC2インスタンスの起動が開始されました。
ここで再度WindowsServerにログインし、ADのコンピュータアカウントを確認してみます。

起動前は既にAD参加済みのWindowsのみ表示されていました。
![ad02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152958/6dd8d269-3b29-5347-4fd8-f84ed10f4bf3.png)

Linux EC2インスタンスの起動完了後、画面を更新すると、コンピュータアカウントが追加されています。
![ad03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152958/6c3648ed-146a-f788-ca90-dfb2670d75de.png)



ドメインユーザーでLinux EC2インスタンスにSSHログインできるか確認してみると、
![ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152958/64f16a5d-698c-74a0-92e4-f84a8140b9e9.png)
無事ログインできました！

# まとめ

Linux EC2インスタンス起動時にシームレスにAD参加する方法を検証しました。
以前は手動でコマンド実行していた関係でドメイン参加が漏れていた、なんてこともありましたが
起動時に自動で参加してくれるのであれば作業漏れありませんね。
これでEC2 AutoScaling時にも活用できそうです。

(2020/11/19追記）
AutoScalingグループで指定するLaunch Templatesでは、参加するドメインの指定ができなさそう。。なので結局はUserDataでゴリゴリやるしかないかなぁ。。