Microsoft Active Directory + FSx for windows を CloudFormation で構築してみよう
はじめに
AWS のソリューションを使って、手軽にファイルサーバーを構築したい & サーバー管理はやりたくないと思い、AWS マネージドの環境を CloudFormation で構築する方法を考えてみました。
あくまで、個人検証用として作成しています。
商用利用の際は下記著作権含め十分検証してからご利用ください。
本記事で触れないこと
- 各 AWS ソリューションの説明や使い方
- CloudFormation テンプレート(yaml)の解説
- 利用料金
AWS構成図
できる限りセキュリティは保証したかったので、プライベートサブネット上で構築しています。
実際は AWS Direct Connect や AWS Site-to-Site VPN を使って、接続することに
なると思います。
YAMLテンプレート
microsoft-ad+fsx-windows.yaml(折り畳んでます)
AWSTemplateFormatVersion: '2010-09-09'
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Network configuration
Parameters:
- AvailabilityZones
- VPCCIDR
- PrivateSubnet1CIDR
- PrivateSubnet2CIDR
- Label:
default: Microsoft Active Directory configuration
Parameters:
- DomainDNSName
- DomainNetBIOSName
- DomainAdminPassword
- ADScenarioType
- Label:
default: FSx for Windows File Server configuration
Parameters:
- NumberOfAZs
- BackupRetention
- DailyBackupTime
- StorageType
- StorageCapacity
- ThroughputCapacity
- FSxEncryptionKey
- FSxExistingKeyID
- FSxAllowedCIDR
- WeeklyMaintenanceTime
ParameterLabels:
AvailabilityZones:
default: Availability Zones
ADScenarioType:
default: Type of Active Directory deployment
BackupRetention:
default: Automated backup retention
DailyBackupTime:
default: Daily backup start time
DomainAdminPassword:
default: Domain admin password
DomainDNSName:
default: Domain DNS name
DomainNetBIOSName:
default: Domain NetBIOS name
FSxEncryptionKey:
default: Type of AWS KMS key used by Amazon FSx
FSxExistingKeyID:
default: AWS KMS key ID
FSxAllowedCIDR:
default: CIDR ranged allowed to connect to FSx file system
NumberOfAZs:
default: Number of Availability Zones
StorageType:
default: Storage type
StorageCapacity:
default: Storage size
ThroughputCapacity:
default: Throughput capacity of Amazon FSx file system
PrivateSubnet1CIDR:
default: Private subnet 1 CIDR
PrivateSubnet2CIDR:
default: Private subnet 2 CIDR
VPCCIDR:
default: VPC CIDR
WeeklyMaintenanceTime:
default: Weekly maintenance start time
Parameters:
AvailabilityZones:
Type: List<AWS::EC2::AvailabilityZone::Name>
ADScenarioType:
AllowedValues:
- AWS Managed Microsoft AD(Enterprise Edition)
- AWS Managed Microsoft AD(Standard Edition)
Default: AWS Managed Microsoft AD(Standard Edition)
Type: String
BackupRetention:
Default: 7
Type: Number
DailyBackupTime:
Default: '01:00'
Type: String
DomainAdminPassword:
AllowedPattern: (?=^.{6,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*
MaxLength: '32'
MinLength: '8'
NoEcho: 'true'
Type: String
DomainDNSName:
AllowedPattern: '[a-zA-Z0-9\-]+\..+'
Default: example.com
MaxLength: '255'
MinLength: '2'
Type: String
DomainNetBIOSName:
AllowedPattern: '[a-zA-Z0-9\-]+'
Default: example
MaxLength: '15'
MinLength: '1'
Type: String
StorageType:
AllowedValues:
- 'SSD'
- 'HDD'
Default: 'SSD'
Type: String
StorageCapacity:
Default: 32
Type: Number
ThroughputCapacity:
Default: 8
Type: Number
FSxEncryptionKey:
AllowedValues:
- 'Default'
- 'GenerateKey'
- 'UseKey'
Default: 'Default'
Type: String
FSxExistingKeyID:
Default: ''
Type: String
FSxAllowedCIDR:
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
Default: 10.0.0.0/16
Type: String
NumberOfAZs:
AllowedValues:
- '1'
- '2'
Default: '1'
Type: String
PrivateSubnet1CIDR:
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
Default: 10.0.0.0/19
Type: String
PrivateSubnet2CIDR:
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
Default: 10.0.32.0/19
Type: String
VPCCIDR:
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$
ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28
Default: 10.0.0.0/16
Type: String
WeeklyMaintenanceTime:
Default: '7:02:00'
Type: String
Conditions:
UseEnterpriseEdition: !Equals
- !Ref 'ADScenarioType'
- 'AWS Managed Microsoft AD(Enterprise Edition)'
IsTwoAz: !Equals
- !Ref 'NumberOfAZs'
- '2'
HasKey: !Equals
- 'UseKey'
- !Ref 'FSxEncryptionKey'
CreateKey: !Equals
- 'GenerateKey'
- !Ref 'FSxEncryptionKey'
UseNonDefault: !Not [!Equals [!Ref 'FSxEncryptionKey', 'Default']]
Resources:
# VPCの作成
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref 'VPCCIDR'
InstanceTenancy: default
EnableDnsSupport: true
EnableDnsHostnames: true
# プライベートサブネットの作成
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref 'VPC'
CidrBlock: !Ref 'PrivateSubnet1CIDR'
AvailabilityZone: !Select ['0', !Ref 'AvailabilityZones']
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref 'VPC'
CidrBlock: !Ref 'PrivateSubnet2CIDR'
AvailabilityZone: !Select ['1', !Ref 'AvailabilityZones']
# ルートテーブルの作成
PrivateSubnet1RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref 'VPC'
PrivateSubnet2RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref 'VPC'
# ルートテーブルとサブネットの紐付け
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref 'PrivateSubnet1'
RouteTableId: !Ref 'PrivateSubnet1RouteTable'
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref 'PrivateSubnet2'
RouteTableId: !Ref 'PrivateSubnet2RouteTable'
# Managed AD 関連
MicrosoftAD:
Type: AWS::DirectoryService::MicrosoftAD
Properties:
Name: !Ref DomainDNSName
Edition: !If [UseEnterpriseEdition, 'Enterprise', 'Standard']
ShortName: !Ref DomainNetBIOSName
Password: !Ref DomainAdminPassword
VpcSettings:
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
VpcId: !Ref VPC
DHCPOptions:
Type: AWS::EC2::DHCPOptions
Properties:
DomainName: !Ref DomainDNSName
DomainNameServers: !GetAtt MicrosoftAD.DnsIpAddresses
VPCDHCPOptionsAssociation:
Type: AWS::EC2::VPCDHCPOptionsAssociation
Properties:
VpcId: !Ref VPC
DhcpOptionsId: !Ref DHCPOptions
DomainMemberSG:
Type: AWS::EC2::SecurityGroup
Metadata:
cfn_nag:
rules_to_suppress:
- id: F1000
reason: "Standard Amazon practice"
Properties:
GroupDescription: Domain Members
VpcId: !Ref VPC
DomainMembersIngressRDP:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref DomainMemberSG
IpProtocol: tcp
FromPort: 3389
ToPort: 3389
SourceSecurityGroupId: !Ref DomainMemberSG
DomainMembersIngressWinRMHTTP:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref DomainMemberSG
IpProtocol: tcp
FromPort: 5985
ToPort: 5985
SourceSecurityGroupId: !Ref DomainMemberSG
DomainMembersIngressWinRMHTTPS:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref DomainMemberSG
IpProtocol: tcp
FromPort: 5986
ToPort: 5986
SourceSecurityGroupId: !Ref DomainMemberSG
# FSx for Windows File Storage 関連
FSxKMSKey:
Condition: CreateKey
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::KMS::Key
Properties:
EnableKeyRotation: true
KeyPolicy:
Version: 2012-10-17
Id: !Ref AWS::StackName
Statement:
- Effect: Allow
Principal:
AWS: !Sub arn:aws:iam::${AWS::AccountId}:root
Action: kms:*
Resource: '*'
- Effect: Allow
Principal:
AWS: '*'
Action:
- kms:Encrypt
- kms:Decrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
- kms:CreateGrant
- kms:ListGrants
- kms:DescribeKey
Resource: '*'
Condition:
StringEquals:
kms:ViaService: !Sub fsx.${AWS::Region}.amazonaws.com
kms:CallerAccount: !Ref AWS::AccountId
Metadata:
cfn-lint:
config:
ignore_checks:
- EIAMPolicyActionWildcard
ignore_reasons:
- EIAMPolicyActionWildcard: Intent assumed for initial migration.
FSxKeyAlias:
Condition: CreateKey
Type: AWS::KMS::Alias
Properties:
AliasName: !Sub alias/${AWS::StackName}
TargetKeyId: !Ref FSxKMSKey
FSxSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC
GroupDescription: Security Group for FSx for Windows File Storage Access
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 53
ToPort: 53
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: udp
FromPort: 53
ToPort: 53
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 88
ToPort: 88
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: udp
FromPort: 88
ToPort: 88
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: udp
FromPort: 123
ToPort: 123
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 135
ToPort: 135
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: udp
FromPort: 389
ToPort: 389
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 389
ToPort: 389
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: udp
FromPort: 445
ToPort: 445
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 445
ToPort: 445
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: udp
FromPort: 464
ToPort: 464
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 464
ToPort: 464
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 636
ToPort: 636
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 3268
ToPort: 3268
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 3269
ToPort: 3269
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 5985
ToPort: 5985
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 9389
ToPort: 9389
CidrIp: !Ref FSxAllowedCIDR
- IpProtocol: tcp
FromPort: 49152
ToPort: 65535
CidrIp: !Ref FSxAllowedCIDR
WindowsFSx:
Type: AWS::FSx::FileSystem
Properties:
FileSystemType: WINDOWS
KmsKeyId: !If
- UseNonDefault
- !If
- HasKey
- !Ref FSxExistingKeyID
- !Ref FSxKMSKey
- !Ref AWS::NoValue
StorageType: !Ref StorageType
StorageCapacity: !Ref StorageCapacity
SubnetIds:
- !Ref PrivateSubnet1
- !If [IsTwoAz, !Ref 'PrivateSubnet2', !Ref 'AWS::NoValue']
SecurityGroupIds:
- !Ref DomainMemberSG
- !Ref FSxSecurityGroup
WindowsConfiguration:
ActiveDirectoryId:
!Ref MicrosoftAD
WeeklyMaintenanceStartTime:
!Ref WeeklyMaintenanceTime
DailyAutomaticBackupStartTime:
!Ref DailyBackupTime
AutomaticBackupRetentionDays:
!Ref BackupRetention
DeploymentType: !If [IsTwoAz, 'MULTI_AZ_1', 'SINGLE_AZ_1']
PreferredSubnetId:
!Ref PrivateSubnet1
ThroughputCapacity:
!Ref ThroughputCapacity
YAMLパラメーターの解説
- Network configuration
パラメーター名 | 解説 | 備考 |
---|---|---|
AvailabilityZones | 利用するAZを2つ選択 | Microsoft Active Directory はAZが2つ必要 |
VPCCIDR | VPCのCIDR | |
PrivateSubnet1CIDR | PrivateSubnet1のCIDR | |
PrivateSubnet2CIDR | PrivateSubnet2のCIDR |
- Microsoft Active Directory configuration
パラメーター名 | 解説 | 備考 |
---|---|---|
DomainDNSName | ルートドメイン | |
DomainNetBIOSName | NetBios名 | |
DomainAdminPassword | Adminのパスワード | 半角英数字 (大文字は最低1文字必要) |
ADScenarioType | ADのタイプを選択 | Enterprise or Standard |
- FSx for Windows File Server configuration
パラメーター名 | 解説 | 備考 |
---|---|---|
NumberOfAZs | FSxをシングルにするか マルチにするか |
1を選択した場合、上記 構成図のAZ2にFSxは 作成されません。 |
BackupRetention | バックアップを保持する日数 | 最大保持期間は35日 0は自動バックアップが 無効になります。 |
DailyBackupTime | バックアップを実行する時間 | |
StorageType | HDD or SSD | シングルAZの場合 HDDは利用不可 |
StorageCapacity | ストレージ容量 | 32 GiB - 65,536 GiB |
ThroughputCapacity | FSxのスループット | 8 - 2048 |
FSxEncryptionKey | 保存時の暗号化 | Default:AWS KMS GenerateKey:キーを作成 UseKey:既存のキーを使用 |
FSxExistingKeyID | AWS KMS Key ID | UseKeyを選択の場合、 AWS KMS Key ID を指定します |
FSxAllowedCIDR | FSxにアクセスを許可する CIDR ブロックを指定します |
|
WeeklyMaintenanceTime | 毎週のメンテナンスを実行 するための希望開始時刻 |
ドメイン参加に関する制約
- Active Directory の種類
Standard Edition または Enterprise Edition を選択可能 - パスワードポリシー
最小8文字、最大32文字
英大文字・小文字・数字・記号を含む必要あり - ドメイン名の形式
FQDN形式(例: example.com)
NetBIOS名は最大15文字 - CIDR制約
FSxAllowedCIDR は /16〜/28 の範囲で指定 - ポート要件(セキュリティグループ)
FSxがADに参加するため以下のポートが必要です。
TCP/UDP: 53, 88, 389, 445, 464
TCP: 135, 636, 3268, 3269, 5985, 9389, 49152-65535
UDP: 123
CloudFormation 実行時のエラー集
AZが2つ選択されていませんので、2つ選択してください。
FSx をシングルAZで構築する場合、StorageType を HDD として作成することができません。
(つまり FSx をシングルAZで構築する場合は、SSD 1択です!)
HDD を利用したい場合は、マルチAZとしてください。
throughputCapacity は 8 ~ 2048 の範囲を選択してください。
StorageCapacity は 32 ~ 65,536 の範囲を選択してください。
Windows11 で検証
- AWS Client VPN で Private Subnet に接続
- 作業PCの hosts に FSx の DNS名(以降「fs-hoge.example.com」とする) と IPアドレスを追加
- エクスプローラーで「\\fs-hoge.example.com」に接続
- ログイン画面が表示されますので、ユーザー名(ルートドメインが「example.com」の場合、「Admin@example.com」です。)と、設定したパスワードを入力し接続
- エクスプローラーの「share」フォルダにアクセスし、ファイルのアップロードなど試してください
- あとはADでユーザーを追加したり、FSxで共有フォルダを作成したりお好きに
まとめ
AWS でファイルサーバー検証を行う場合、サクッと構築できるかなと思います。
個人で検証する場合は、AWS Client VPN を利用すると良さそうです。
(別の機会にまとめてみます)
この記事が、誰かの役に立てば幸いです。
参考サイト
-
本記事で紹介しているテンプレートは、以下のGitHubリポジトリに基づいています。
https://github.com/aws-ia/cfn-ps-fsx-windows-file-server?tab=readme-ov-file -
このテンプレートは以下の著作権のもとで提供されています。
https://github.com/aws-ia/cfn-ps-fsx-windows-file-server/blob/main/NOTICE.txt -
このコードは Apache License 2.0 の下で提供されています。
https://www.apache.org/licenses/LICENSE-2.0
参考サイトとの変更点
- パブリックサブネットは作成しません
- NAT gateway、RD Gateway および AutoScalling group は作成しません
- 2つのプライベートサブネット構成に固定しました
- Active Directory domain controller および Domain controller security group は作成しません
Discussion