DEV Community

Cover image for EC2インスタンス作成時にホスト名変更&AD参加する(UserData編)
ryanc
ryanc

Posted on

EC2インスタンス作成時にホスト名変更&AD参加する(UserData編)

検証環境でWindows Serverをたくさんたてるのだが、
①(AWS Managed ADではない)ADに参加
②ホスト名を、自分がつけたNameタグの値に揃える
これはだいたい必ずやる。②に関しては、自動的につけられるランダムなホスト名だと分かりづらいので早々に自分がつけたい名前にしておきたいという意図。



これを一々手動でやるのはとても面倒なので(再起動も発生するし)、もちろん自動化したい。自動化する方法は色々あるが、今回は一番原始的(?)UserDataスクリプトを利用する方法を使ってみる。

ちなみにUserDataスクリプトはインスタンス作成時の一回しか実行されないので、少々柔軟性にかけるし、何かしらの問題でスクリプト実行が失敗したら手動で直さないといけない。とはいえアドホックでやるには簡単な方法だし楽な場合もある。

AWS Managed ADを使う場合は、インスタンス作成時に簡単に指定できちゃうのだが、EC2上に構築したADや、オンプレのAD等の場合はこういう方法を使う必要がある。



ドメイン参加にはその権限を持ったドメインアカウントが必要なのだが、その認証情報をスクリプトにハードコードしたくはないのでSecrets Managerを使うとしよう。

「その他シークレット」のタイプで作成。
参加するドメインはonprem.example.comという設定だ。
image

こんな感じでドメインアカウントのユーザー名とパスワードを設定しておく(もちろん、コンピュータをドメイン参加させる権限のあるアカウントを使ってね)。
image

onprem.example.com/DomainJoinという名前でシークレットを作成した。
image



ここから先は、EC2インスタンスプロファイル(IAMロール)にこの2つの権限が必要になってくる。
①さきほど作成したシークレットonprem.example.com/DomainJoinを読み取る権限
②EC2のタグを読み取る権限(Nameタグの値を読み取って、ホスト名に使う必要があるので)

こんな感じのポリシーを最低限追加しておく必要あり。

"Statement": [
        {
            "Sid": "ReadTag",
            "Effect": "Allow",
            "Action": "ec2:DescribeTags",
            "Resource": "*"
        },
        {
            "Sid": "SecretsMgrRead",
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue"
            ],
            "Resource": "arn:aws:secretsmanager:<リージョン>:<AWSアカウント番号>:secret:onprem.example.com/DomainJoin-tewFSS"
        }
    ]
Enter fullscreen mode Exit fullscreen mode

secretsmanager:GetSecretValueアクションの権限で指定するResourceの値は、さきほど作成したシークレットのARNを代入する。Secrets Managerで簡単に確認できる。
image



これで準備が揃ったので、こういうスクリプトをUserDataに貼り付けて、Windows ServerのEC2インスタンスをたてる。
※AWS Tools for PowerShellを使うので、Amazonが提供する標準Windows ServerのAMIを使っていることを想定。自前のAMIを使うのであれば、AWS Tools for PowerShellをイメージにあらかじめ入れておく必要あり。

<powershell>
# ドメイン名とシークレット名を定義
$domainName = "onprem.example.com"
$secretName = "onprem.example.com/DomainJoin"

# シークレットの値をとってくる
$secretManager = Get-SECSecretValue -SecretId $secretName

# シークレットの値をオブジェクトに入れる
$secret = $secretManager.SecretString | ConvertFrom-Json

# ドメイン参加用認証情報を作成
$username = $domainName + "\" + $secret.Account
$password = $secret.Password | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($username,$password)

# EC2インスタンスメタデータからインスタンスIDを取得し、続けてNameタグを取得
$instanceID = Get-EC2InstanceMetadata -Category InstanceId
$nameTag = Get-EC2Tag -Filter @{Name="resource-id";Value="$instanceID"},@{Name="key";Value="Name"}
$newName = $nameTag.Value

# ドメイン参加を実施
Add-Computer -DomainName "$domainName" -NewName "$newName" -Credential $credential -Passthru -Force -Restart
</powershell>
Enter fullscreen mode Exit fullscreen mode



これで、EC2インスタンス作成と同時にドメイン参加・ホスト名変更までできた。ローカルアドミンのパスワードを一度も復号化する必要なくドメインアカウントでログインできるので便利。



ちなみに、ドメイン参加のためにはドメインコントローラーを名前解決できる必要があるので、
①Route 53 Resolverのアウトバウンドエンドポイントを作成し、ルールでADドメインの名前は、ADのDNSサーバーにルーティングさせる
②DHCPオプションセットを設定しておく
③UserDataスクリプトに、DNS設定をADに向けるように設定する操作を追加する
のどれかをする必要はある(他にも方法あるかも)。
私の場合は、①を設定しているので他の設定は特に不要。



次回にはSystems Manager Automationを使う方法かChefを使う方法を試そうかなと思う。



※イラストはこちらからご提供いただきました:
Computer vector created by macrovector - www.freepik.com

Top comments (0)