EC2 InstanceをAmazon Managed ADに自動Joinする流れをCloudFormationでやってみた

# CloudFormationでEC2 Instanceを作成してADにJoinする流れを自動化したい
* Cloud Nativeの領域に仕事をしているエンジンニアとして、どうやって自分の作業をできるだけ自動化することをよく考えてます。最近AWS上にMS AD関連の技術検証が多いので、CloudFormationでEC2インスタンスとADの作成と連携の流れを自動化してみたいです！
* フローチャットは以下のようになります:
![Picture1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781205/a07a0511-09cc-9295-592e-383a48cc9c96.png)

# Keyword
* CloudFormation
    * インフラストラクチャをコードとして扱うことで、AWS およびサードパーティーのリソースをモデル化、プロビジョニング、管理することができます。
* Amazon Managed AD
    * AWSが管理するマネージドなActive Directoryサービスです。AWSクラウドで簡単にディレクトリをセットアップして実行したり、AWS リソースを既存のオンプレミス Microsoft Active Directory に接続したりできます。
* YAML
    * 構造化データやオブジェクトを文字列にシリアライズ（直列化）するためのデータ形式の一種。テキストのため可読であることは特徴です。

# いきなりまとめ
* CloudFormationでADにJoinするまで自動化できる？
    * はい、できます！
* どうやって実現できた？
    * SSM（AWS Systems Manager）を使って実現できました！ 
# YMALコード
https://github.com/NetAppJpTechTeam/FSxN-Demo-Environment/blob/development/aws_managed_ad_setup.yaml

# テンプレート詳細：パラメータの設定
```yaml:Parameters
  AvailabilityZones:
    Description: Select two 2 Availability Zones (AZ).
    Type: List<AWS::EC2::AvailabilityZone::Name>
  InstanceType:
    Description: Select the instance type.
    AllowedValues:
    - t2.micro
    - m5.large
    - c5n.xlarge
    - c5n.2xlarge
    - c5n.9xlarge
    - c5n.18xlarge
    - r5n.8xlarge
    - r5n.16xlarge
    - r5n.24xlarge
    Default: t2.micro
    Type: String
  KeyPair:
    Type: AWS::EC2::KeyPair::KeyName
  VpcCidr:
    AllowedValues:
    - 10.0.0.0/16
    - 173.31.0.0/16
    - 192.168.0.0/16
    Default: 10.0.0.0/16
    Description: Select the private IPv4 CIDR for the VPC.
    Type: String
  LatestWindowsAmiId:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: '/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base'
  DirectoryPassword:
    NoEcho: true
    Description: The password for your MS Directory Admin.
    Type: String
```
今回のテンプレートは最初に以下のパラメーターを入力できます：
* AvailabilityZones
    * 現在CloudFormationを実行するリージョンに使用可能なAZを選択できます。
    * Amazon Managed ADはMulti-AZの構造なので、二つAZを選択してください。
* InstanceType
    * Windows Instanceを立ち上げる時のインスタンスタイプを選択します。
    * デフォルトは一番安いt2.microです。
* KeyPair
    * 現在CloudFormationを実行するリージョンに使用可能なKeyPairを選択します。
    * 選択できない場合、現在のリージョンにはKeyPairを作ってないことを示します。
    * KeyPairの作成手順：https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/create-key-pairs.html
* VpcCidr
    * テンプレートで作成するネット環境で、VPCのサイダー（CIDR）を選択できます。
    * CIDRとは：https://www.nic.ad.jp/ja/basics/terms/cidr.html
* LatestWindowsAmiId
    * 最新のWindows InstanceのAMIを取得します。
    * デフォルトはWindows_Server-2022-EnglishのOSがデプロイされています。
    * 修正したい時はUrlを変更してください。
* DirectoryPassword
    * 作成されたADのパスワードを指定できます。
    * 今回は検証環境なので、Secret Managerを使ってないです。


# テンプレート詳細：EC2 InstanceとAmazon Managed ADの作成
```yaml:Windows Instance & Role 
  #The Windows OS Instance
  WindowsInstance:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref InstanceProfile
      ImageId: !Ref LatestWindowsAmiId
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyPair
      Monitoring: true
      SecurityGroupIds:
        - !Ref SecurityGroup
      SubnetId: !Ref PublicSubnet0
      Tags:
        - Key: Name
          Value: AD_Join test Windows Instance

  # Instance Role Setting
  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: '/'
      Roles:
      - !Ref InstanceRole

  InstanceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - ec2.amazonaws.com
          Action:
          - sts:AssumeRole
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
      - arn:aws:iam::aws:policy/AmazonFSxFullAccess
      - arn:aws:iam::aws:policy/AmazonEC2FullAccess
      - arn:aws:iam::aws:policy/IAMFullAccess
      - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      - arn:aws:iam::aws:policy/AmazonSSMDirectoryServiceAccess
      Path: "/"
```
この部分はWindows Instanceと使うIAM Roleを作成します。
* AMI、Key Pair、Instance Typeは最初パラメーター入力のところ指定しました。
* サブネットとアタッチするセキュリティグルプはネットリソースのところに構築しました。
    * 省略しましたが、コードの７６行から１８０行までご参照ください。
* 今回はSSMのドキュメンテーションを使ってEC2 InstanceをADにJoinするので、SSMの権限も追加しました。



```yaml:Managed AD
  #AWS Managed Microsoft AD
  MSDirectory:
    Type: AWS::DirectoryService::MicrosoftAD
    Properties:
      Edition: Standard
      Name: example.com
      Password: !Ref DirectoryPassword
      VpcSettings:
        SubnetIds:
          - !Ref PublicSubnet0
          - !Ref PublicSubnet1
        VpcId:
          !Ref Vpc
```
この部分はWindows Instanceと使うIAM Roleを作成します。
* ドメインはexample.comを設定されてます。
* サブネットとVPCはネットリソースのところに構築しました。
    * 省略しましたが、コードの７６行から１８０行までご参照ください。


# テンプレート詳細：作成されたWindows InstanceをAmazon Managed ADにJoin
```yaml:Join AD 
  AWSJoinDirectoryServiceDomainAssociation:
    Type: AWS::SSM::Association
    DependsOn:
          - WindowsInstance
          - MSDirectory
    Properties:
      AssociationName: "example-aws-join-directory-service-domain-association"
      Name: AWS-JoinDirectoryServiceDomain
      Parameters:
        directoryId:
          - !Ref MSDirectory
        directoryName:
          - example.com
        directoryOU:
          - OU=Computers,OU=example,DC=example,DC=com
        dnsIpAddresses:
          - !Select [0, !GetAtt MSDirectory.DnsIpAddresses]
          - !Select [1, !GetAtt MSDirectory.DnsIpAddresses]
      Targets:
        - Key: InstanceIds
          Values:
            - !Ref WindowsInstance
      WaitForSuccessTimeoutSeconds: 3000
```
この部分は作成されたInstanceをADにJoinします！
* AWSが提供するドキュメントAWS-JoinDirectoryServiceDomainのRun Commandを使用します。
* directoryOUのところは必ず指定してください。
    * 指定しないとCloudFormationはエラーなしで実行完了しますが、効果がありません（Amazon Managed ADにJoinする場合）。
* DependsOnのとこる、リソースのインスタンスとADを指定して、正しい作成順番を決めました。
    * dnsIpAddressesに作成されたADのDNS IPアドレスを指定する必要があります。
    * Targetsに作成されたインスタンスを指定する必要があります。
# Reference
* [KeyPairの作成手順](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/create-key-pairs.html)
* [CIDRとは](https://www.nic.ad.jp/ja/basics/terms/cidr.html)
* [ドキュメンテーション AWS::DirectoryService::MicrosoftAD](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-directoryservice-microsoftad.html)
* [ドキュメンテーション AWS::EC2](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/AWS_EC2.html)
* [ドキュメンテーション AWS CloudFormation Parameters](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html)
* [How do I use AWS Systems Manager to join a running EC2 Windows instance to my AWS Directory Service domain?](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-systems-manager-dx-domain/)