AWSPowerShellのコマンド操作でEC2を作成して、ドメイン名でRDP接続するまで

# 概要
## この記事で行うこと

PowerShellからAWSを操作していく様子を記録します。
操作の一例として参考になる記事を目指します。
尚、ここで行う内容は学習目的の設定になるので、運用などを目的とする場合は、[公式ドキュメント](https://docs.aws.amazon.com/powershell/latest/reference/)をご確認ください。

## なぜ記事にするか
AWSPowerShellを使ってAWSを操作する日本語の記事が少なく、一つ一つ調べるのに時間がかかりました。
また、[公式ドキュメント](https://docs.aws.amazon.com/powershell/latest/reference/)の引数の説明も自分にはすっと入ってこず、ここでも手こずりました。
もし似たようなことをしたい方がいれば、全体のイメージを掴む参考にして頂ければと思います。

## AWS操作の流れ
1. リモートデスクトップ接続を許可するセキュリティグループの作成
1. EC2インスタンスの作成
1. EC2インスタンスのWindowsパスワードを取得
1. Elastic IPを作成してEC2インスタンスへ設定
1. Route 53へElastic IPを使ってドメイン名を登録

最後に、ドメイン名でリモートデスクトップ接続できることを確認して終了です。

:::note warn
注意
私が学習した環境では、既にRoute 53にホストゾーンが作成された状態でした。
ですので、Route 53でホストゾーンを作成する手順は含まれていません。
:::


# PowerShellからAWSを操作する
事前に必要な設定については[こちら](https://qiita.com/kkksssyyy/items/3e137e89b0fb22aecba5)を参考にしてください。
ちなみに今回必要な事前準備は以下となります。
```bash:PowerShell
Install-Module -Name AWS.Tools.Installer
Install-AWSToolsModule AWS.Tools.Common -CleanUp
Install-AWSToolsModule -Name AWS.Tools.EC2 -CleanUp
Install-AWSToolsModule -Name AWS.Tools.Route53 -CleanUp
Import-Module AWS.Tools.EC2
Import-Module AWS.Tools.Route53
Set-AWSCredential -AccessKey "xxxxxxxxxxxxxxxx" -SecretKey "xxxxxxxxxxxxxxxx" -StoreAs "xxxx"
```

これから記述するコードは、わかりやすさの為に日本語のコメントを含めています。
しかし、日本語を含めたコードをPowerShellで実行するとエラーになる事がありますので、実行する際は日本語を含めないようにご注意ください。

## リモートデスクトップ接続を許可するセキュリティグループの作成


```bash:PowerShell
# リージョンを設定
Set-DefaultAWSRegion -Region xx-xxxxx-xx
# インスタンス名を設定
$instanceName = "test_instance"
# VPC IDを設定
$vpcId = "vpc-xxxxxxxx"
# セキュリティグループで許可するインバウンドルールを作成
$ipPermissions = New-Object System.Collections.Generic.List[Amazon.EC2.Model.IpPermission]
# リモートデスクトップ接続を許可
$ipPermissions = @(
    @{
        IpProtocol = "tcp"
        FromPort   = 3389
        ToPort     = 3389
        IpRanges   = "0.0.0.0/0"
    }
)

# セキュリティグループのタグを作成
$tagSpecificationSg = @{
        ResourceType = "security-group";
        Tags         = @(
        @{Key = "Name"; value = $instanceName }
    );
}

# セキュリティグループを作成
$securitygroupId = New-EC2SecurityGroup `
    -GroupName $instanceName `
    -Description $instanceName `
    -TagSpecification $tagSpecificationSg `
    -VpcId $vpcId

# セキュリティグループにリモートデスクトップ接続を許可するように設定
Grant-EC2SecurityGroupIngress `
    -GroupId $securitygroupId `
    -IpPermissions $ipPermissions

```

## EC2インスタンスの作成
```bash:PowerShell
# EC2のタグを作成
$tagSpecificationEs2 = @{
        ResourceType = "instance";
        Tags         = @(
        @{Key = "Name"; value = $instanceName }
    );
}

# EC2を作成
# 引数間のコメントは削除して実行してください
$instance = New-EC2Instance `
    # 使用するAmazonマシンイメージのID
    -ImageId "ami-xxxxxxxxxxxxxx" `
    -InstanceType "t3.medium" `
    # 使用するキーペア名
    -KeyName "xxxxxxx" `
    -SecurityGroupId $securityGroupId `
    -BlockDeviceMapping @{ DeviceName = "/dev/sda1"; Ebs = @{ VolumeSize = 50; VolumeType = "gp2" } } `
    -EbsOptimized $true `
    -TagSpecification $tagSpecificationEs2
```

## EC2インスタンスのWindowsパスワードを取得
```bash:PowerShell
# ダウンロード済みの秘密鍵ファイルのパスを設定
$pemFilePath = "C:\xxxxx\xxxxx\xxxx\xxxx\xxxxx.pem"
# インスタンスIDを設定
$instanceId = "i-xxxxxxxxxxx"
# Windowsパスワードを取得
$passwordData = Get-EC2PasswordData -InstanceId $instanceId -Decrypt -PemFile $pemFilePath
```

## Elastic IPを作成してEC2インスタンスへ設定
```bash:PowerShell
# Elastic IPのタグの名前を設定
$tagName = "xxxxxxxxxxxx"
# Elastic IPのタグを作成
$tagSpecificationEip = @{
        ResourceType = "elastic-ip";
        Tags         = @(
        @{Key = "Name"; value = $tagName }
    );
}

# Elastic IPを作成
$allocatedAddress = New-EC2Address -Domain vpc -TagSpecification $tagSpecificationEip
# Elastic IPをEC2インスタンスへ設定
Register-EC2Address -InstanceId $instanceId -PublicIp $allocatedAddress.PublicIp
```

## Route 53へElastic IPを使ってドメイン名を登録
```bash:PowerShell
# パブリックIPを設定
$publicIp = "xxx.xxx.xxx.xxx"

# AレコードをUPSERTするためのインスタンスを作成
$change = New-Object Amazon.Route53.Model.Change
$change.Action = "UPSERT"

$resourceRecordSet = New-Object Amazon.Route53.Model.ResourceRecordSet
# ドメイン名を設定
$resourceRecordSet.Name = "xxxxx.com"
$resourceRecordSet.Type = "A"
$resourceRecordSet.TTL = 300
$resourceRecordSet.ResourceRecords.Add((New-Object Amazon.Route53.Model.ResourceRecord($publicIp))) 


$change.ResourceRecordSet = $resourceRecordSet
$changeBatch = @($change)

# ホストゾーンIDを設定
$hostedZoneId = "/hostedzone/xxxxxxxxxxx"

# ホストゾーンに対してAレコードをUPSERT
$result = Edit-R53ResourceRecordSet -HostedZoneId $hostedZoneId -ChangeBatch_Change $changeBatch
```

## ドメイン名でリモートデスクトップ接続できることを確認
上記で設定したドメイン名と、取得したパスワードでリモートデスクトップ接続してみてください。
成功すれば、一連のAWS操作の練習としては終了となります。

作業後は、インスタンスの停止忘れや残物削除忘れにご注意ください。

# まとめ
PowerShellからの操作と、普段AWSコンソール画面から行っている操作が直感的に結び付かず、私は苦戦してしまいました。
もしかすると全く別物として捉えたほうが理解しやすいのではないかと思います。
同じような方がいた場合、この記事が少しでも理解の役に立ったなら幸いです。