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


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

Amazon EC2 for Linux インスタンスを AWS Directory Service にシームレスに参加させる

ということでLinuxインスタンスデプロイ時にAD参加させる方法を検証してみました。
ちなみに、冒頭で触れた今までのAD参加方法はこちら↓↓
Linux インスタンスを手動で結合する

今回検証した手順はこちら↓↓
Linux EC2インスタンスをシームレスに参加 AWS Managed Microsoft AD ディレクトリ

前提条件

まず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 ※作成済み

では、検証

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

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

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

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

$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にサービスアカウント名とパスワードを指定します。

  2. Secret nameを指定します。

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

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

IAMロールの作成

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

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

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

  • 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: 以下のスクリプトを指定
#!/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のみ表示されていました。

Linux EC2インスタンスの起動完了後、画面を更新すると、コンピュータアカウントが追加されています。

ドメインユーザーでLinux EC2インスタンスにSSHログインできるか確認してみると、

無事ログインできました!

まとめ

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

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