Systems Manager Run CommandでAWS Managed Microsoft ADを操作する
Tags: aws, windows, activedirectory, dns
Published: 2021-05-11 03:06:20

AWS Managed Microsoft AD（以下Managed AD）を管理するには、リモート管理ツールをインストールした管理用サーバー（または踏み台サーバー）が別途必要なのが世の常だが。。オペレーションを自動化したい、またはサーバーにリモートデスクトップすることなくPowerShellコマンドレットを実行してぱぱっとやっちゃいたい、と思うこともあるだろう。

そう、まさにSystems Manager Run Commandで普通のWindows Server EC2インスタンスに対してできるように。

<br>
ただ、これにはハードルが2つある。

①Managed ADのドメインコントローラーはEC2インスタンスじゃないので、Run Commandのターゲットに指定できない

②Run Commandはインスタンスのローカルシステムアカウントとして実行されるのだが、ドメインコントローラーに対する操作はそれなりの権限を持った「ドメインユーザー」として実行する必要がある

<br>
①に関しては、直接ドメインコントローラーに対してではなく、同じドメインに属している別のEC2インスタンスに対して実行し、そのコマンド自体がドメインコントローラーに対して操作を実行するという構図にしよう。

`結局踏み台必要じゃないか！`
というツッコミは華麗にスルーして、「でもリモートデスクトップする必要はないし、Run Commandが実行できる条件さえ整っていればどのサーバーでもいいよ」とつぶやいてみる。

ちなみに、PowerShell CoreをLambda関数に載せて完全にサーバーレスでできたら美しいだろうな。。しかしAD関連をPowerShell Coreでやるのはかなりややこしくなるのでここでは原始的に踏み台サーバーを使うとしよう。

<br>
②に関しては、実行したいコマンドレットに依存するが、別のユーザーとして実行する機能を活用する。詳しくは実際の実行サンプルにて。

<br>
用意するもの：
a. ドメインユーザーの認証情報を保存したSecrets Managerシークレット

b. Secrets Managerシークレットを参照できるEC2インスタンスプロファイル

c. Systems Manager Run Commandを実行でき、かつManaged ADのドメインに参加しているWindows ServerのEC2インスタンス

d. Systems Manager Run Commandドキュメント

<br>
a.とb.は、[この投稿](https://dev.to/ryanch79/ec2-ad-userdata-19k6)と作成の仕方は同じなのでどうぞご参考に。

<br>
c.は各自調達しましょうね。

<br>
d.を次のように作成してみた。

今回は、ちょっとややこしいDNSフォワーダ設定をしてみるとしよう。

柔軟性のあるドキュメントにしたいので、パラメータを次のように設ける。

* DomainController1: DNSサーバーのIPアドレス（その一）
* DomainController2: DNSサーバーのIPアドレス（その二）
* DNSForwardDestination: DNSフォワード先のIPアドレス
* UserCredentialSecretID: ドメインユーザーの認証情報が格納されているSecrets ManagerシークレットのID

Managed ADのDNSサーバーはドメインコントローラー上にあるので、Directory Serviceの管理コンソールからIPアドレスを確認できる。

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s9bfbkic9j6ody8wbn80.png)

以下、Run Commandドキュメント。
```
---
schemaVersion: "2.2"
description: "Overwrites DNS Forwarder settings"
parameters:
  DomainController1:
    type: String
    description: "コマンド実行する対象のDNSサーバーのIPアドレス（その一）"
  DomainController2:
    type: String
    description: "コマンド実行する対象のDNSサーバーのIPアドレス（その二）"
  DNSForwardDestination:
    type: String
    description: "設定したいDNSのフォワード先IPアドレス"
  UserCredentialSecretID:
    type: String
    description: "AD参加に利用するユーザー認証情報を保持するSecrets ManagerシークレットID"
mainSteps:
- action: "aws:runPowerShellScript"
  name: "addDnsForwarder"
  inputs:
    runCommand: 
    - $secretManager = Get-SECSecretValue -SecretId "{{UserCredentialSecretID}}"
    - $secret = $secretManager.SecretString | ConvertFrom-Json
    - $username = $secret.Username
    - $password = $secret.Password | ConvertTo-SecureString -AsPlainText -Force
    - $credential = New-Object System.Management.Automation.PSCredential($username,$password)
    - $cimsession = New-CimSession -Credential $credential
    - Write-Output "Overwriting DNS Forwarder setting  ----"
    - Add-DnsServerForwarder -CimSession $cimsession -ComputerName {{DomainController1}} -IpAddress {{DNSForwardDestination}} -PassThru
    - Add-DnsServerForwarder -CimSession $cimsession -ComputerName {{DomainController2}} -IpAddress {{DNSForwardDestination}} -PassThru
```

<br>
各パラメータをうまく当てはめて、PowerShellで`Add-DnsServerForwarder`コマンドレットを実行するだけ。

<br>
実際にこのドキュメントをRun Commandで実行してみて、問題なくDNSフォワーダの設定が入ったことを確認。よかった。

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o09yfxs6cjo2hrn02343.png)

ドキュメントにしてしまえば、EventBridgeで定期実行するとか、アドホックでAWSコンソールから実行するとかもできるので、サーバーにログインする必要がなくなり便利だしセキュリティも向上する。
 
<br>
ちなみに、ここでポイントになるのが`Add-DnsServerForwarder`を「ドメインユーザー」として実行できるかという話。

このコマンドレットは`-CimSession`スイッチがあるので、他のユーザーとしてのセッションとして実行することができる。他にも`-Credential`等のスイッチを持っているコマンドレットならできるが。。そういったスイッチを持っていないコマンドレットだと一気にややこしくなる。

ということで今日は以上。