[アップデート] RDS for SQL ServerがセルフマネージドなActive Directoryドメインに参加できる様になりました

2023.07.28

しばたです。

少し前のはなしですが、RDS for SQL ServerがセルフマネージドなActive Directoryドメインに参加できる様になりました。
AWSからのアナウンスはこちらになります。

アナウンスの内容はシンプルにまとめられていますが、実際にはかなりの制限がありますので本記事で詳しく解説したいと思います。

従来との違い

従来RDS for SQL ServerはAWS Managed Microsoft ADのドメインに参加してドメインユーザーによるWindows認証接続が可能でした。

AD Connectorの利用はサポートされておらず「RDS for SQL ServerでWindows認証接続したい場合はAWS Managed Microsoft ADの利用が必須」であり、例えばオンプレ環境にあるセルフマネージドなActive Directory環境を対象にするにはAWS Managed Microsoft ADと信頼関係を結ぶ必要がありました。

今回の更新により「RDS for SQL ServerがセルフマネージドなActive Directoryに直接参加する」ことが可能となります。

制限事項

これだけ聞くと非常に便利なアップデートに見えますが、実際には多くの制限事項があります。
AWSのドキュメントから引用すると以下の通りです。

  • NTLM is the only supported authentication type. Kerberos authentication is not supported. If you need to use kerberos authentication, you can use AWS Managed AD instead of self-managed AD.
  • The Microsoft Distributed Transaction Coordinator (MSDTC) service isn't supported, as it requires Kerberos authentication.
  • Your RDS for SQL Server DB instances do not use the Network Time Protocol (NTP) server of your self-managed AD domain. They use an AWS NTP service instead.
  • SQL Server linked servers must use SQL authentication to connect to other RDS for SQL Server DB instances joined to your self-managed AD domain.
  • Microsoft Group Policy Object (GPO) settings from your self-managed AD domain are not applied to RDS for SQL Server DB instances.

制限1. 認証方式

セルフマネージドなActive Directoryに参加した場合、使える認証方式はNTLM認証のみです。
Kerberos認証による接続はできません。
加えてKerberos認証を前提とする分散トランザクションコーディネーター (MSDTC) の利用も非サポートです。

制限2. リンクサーバー

RDS for SQL Serverインスタンスからリンクサーバーを使って別のSQL Serverに接続する際はSQL認証のみ可能です。Windows認証はできません。

制限3. NTPサーバー

RDS for SQL Serverインスタンスが使用するNTPサーバーはAWS NTP Serviceで強制されドメインで指定されたNTPサーバーを利用することはできません。

制限4. グループポリシー

RDS for SQL Serverインスタンスに独自のグループポリシーを適用することはできません。

所感

何故この様な制限が掛けられているかの理由については明記されていません。
いろいろ調べてみたものの明確な理由を見出すことはできませんでした...予想としては「技術的な制約とRDSインスタンスの保護がそれぞれ絡み合っているのかな?」と感じています。

運用上の注意点

RDSインスタンスをリストアする際は都度ドメインに参加しなおす必要があります。

バックアップされる情報にドメインへの登録情報が無いのに加え、リストアする都度別の実体(インスタンス)になる都合これは仕方の無い点になるかと思います。

前提条件

ここからはこの機能を使うための前提条件を解説します。

Active Directory環境

本機能が使えるAD側の要件は以下となっています。

  • ドメインの機能レベルがWindows Server 2008 R2以降であること
  • シングルラベルドメイン(SLD)は非サポート
  • ドメインのFQDNおよびOUの文字数が64文字を超えないこと
  • サイトの定義をしている場合、RDSのあるサブネットが適切に設定されていること

こちらはあまり気にしないで大丈夫でしょう。

ネットワーク要件

次にRDSインスタンスがドメインに参加するためRDSインスタンス→ドメインコントローラーの疎通を可能にしておく必要があります。

(https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_SQLServer_SelfManagedActiveDirectory.html より引用)

使うポートの一覧は以下の通りです。

プロトコル ポート番号 役割
TCP/UDP 53 DNS
TCP/UDP 88 Kerberos認証
TCP/UDP 464 Kerberos set-password
TCP/UDP 389 LDAP
TCP 135 DCE / EPMAP
TCP 445 SMB
TCP 636 LDAPS
TCP 49152 - 65535 RPC用エフェメラルポート

基本的にADで使うポートそのまま空けると考えておけばOKです。

AWS側要件

最後に、RDSインスタンスをドメインに参加させる際に専用のユーザーアカウントを用意する必要があり、その認証情報をAWS Secrets Managerに登録する必要があります。

Secrets ManagerにアクセスするのはRDSサービスとなり、このため別途独自のポリシーを定義したKMSカスタマーキーを用意する必要があります。

従来AWS Managed Microsoft ADを使ってWindows認証をする際はRDSインスタンスに独自のロールが付与されましたが、本機能ではIAMロールのアタッチはありませんのでご注意ください。

試してみた

だいぶ前置きが長くなりましたがここから実際に試していきます。

今回は私の検証用AWSアカウントの東京リージョンで試します。
VPC等のネットワーク周りの環境は構築済みの状態からスタートします。

0. 構成図

全体像としては下図の様になります。

予め用意したVPC内にドメインコントローラーとなるWindows Server 2022 EC2を1台用意し、同じサブネットにRDS for SQL Server 2019 Standard Edtionの環境を作って試します。

1. ドメインコントローラーの準備

ドメインコントローラーとなるEC2は本日時点最新の日本語版Windows Server 2022 AMIから作っています。

  • ami-0a5d4bae8f609a806 : Windows_Server-2022-Japanese-Full-Base-2023.07.12

EC2インスタンスの構築手順は割愛します。
また、セキュリティグループも「前提条件」に記載されたポートを解放する設定にしてあります。

ドメインの作成

その上で、ドメインcorp.contoso.comを以下のPowerShellコマンドで構築しています。

# ※インターネットアクセス不可の環境でもOK

# Windows機能の追加
Add-WindowsFeature AD-Domain-Services, GPMC, RSAT-ADDS, RSAT-AD-PowerShell, RSAT-DNS-Server | Format-List

# ドメイン作成+再起動
Import-Module ADDSDeployment
$params = @{
    DomainName        = 'corp.contoso.com';
    DomainNetbiosName = 'CORP';
    ForestMode        = 'WinThreshold';
    DomainMode        = 'WinThreshold';
    DatabasePath      = 'C:\Windows\NTDS';
    LogPath           = 'C:\Windows\NTDS';
    SysvolPath        = 'C:\Windows\SYSVOL';
    SafeModeAdministratorPassword = (ConvertTo-SecureString 'P@ssword' -AsPlainText -Force);
    InstallDns           = $true;
    CreateDnsDelegation  = $false;
    NoRebootOnCompletion = $false;
    Confirm = $false;
}
Install-ADDSForest @params

専用OU、専用ユーザーの作成

ドメインが出来上がった後、

  • RDSインスタンス専用のOU
  • RDSインスタンスをドメインに参加させるための専用ユーザー

を用意します。
AWSとして専用のOUと管理ユーザーを作ることが推奨されています。

We recommend creating a dedicated OU and service credential scoped to that OU for any AWS account that owns an RDS for SQL Server DB instance joined your self-managed AD domain. By dedicating an OU and service credential, you can avoid conflicting permissions and follow the principal of least privilege.

今回は、

  • RDSInstances OU
  • rdssql@corp.contoso.com 管理ユーザー

を以下のPowerShellコマンドで作成しました。

# RDSInstances という専用OUを用意
New-ADOrganizationalUnit -Name 'RDSInstances' -Path 'DC=corp,DC=contoso,DC=com'

# rdssql ユーザーを作成
$params = @{
    Name                 = 'rdssql';
    UserPrincipalName    = 'rdssql@corp.contoso.com';
    Description          = 'RDS for SQL Server service user';
    AccountPassword      = ConvertTo-SecureString -AsPlainText 'P@ssword' -Force;
    Enabled              = $true;
    PasswordNeverExpires = $true;
}
New-ADUser @params

(専用OU)

(専用ユーザー)

専用ユーザーの権限設定 (制御の委任)

続けてrdssql@corp.contoso.comユーザーに必要な権限を与えていきます。

はじめに「Active Directoryユーザーとコンピューター」を起動し、RDSInstancesOUを右クリックして「制御の委任」をクリックします。

ウィザードが開始されるので「次へ」をクリック。

選択されたユーザーとグループにrdssql@corp.contoso.comユーザーを追加して「次へ」をクリック。

委任するタスクは「委任するカスタムタスクを作成する」を選び「次へ」をクリック。

対象オブジェクトは下図の様に選び「次へ」をクリック。

  • 「フォルダー内の次のオブジェクトのみ」を選択
    • 「コンピューターオブジェクト」にチェック
  • 「選択されたオブジェクトをこのフォルダーに作成する」にチェック
  • 「選択されたオブジェクトをこのフォルダーから削除する」にチェック

アクセス許可は下図の様に選び「次へ」をクリック。

  • 「全般」にチェック
  • アクセス許可欄の以下の項目にチェックを付ける
    • 「DNSホスト名への検証された書き込み」
    • 「サービスプリンシパル名への検証された書き込み」

最後に指定内容に間違いがないことを確認して「完了」をクリック。

確認メッセージ全文

次の Active Directory フォルダー内のオブジェクトの
制御を委任することを選択しました:

    corp.contoso.com/RDSInstances

制御を与えたグループ、ユーザー、または
コンピューター:

    rdssql (rdssql@corp.contoso.com)

次のアクセス許可が与えられています:

    DNS ホスト名への検証された書き込み
    サービス プリンシパル名への検証された書き込み

次のオブジェクトの種類:

    コンピューター

これでrdssql@corp.contoso.comユーザーがRDSInstancesOUに対する所定の権限を持つことになります。

これでドメインコントローラーの準備は完了です。

2. KMSの準備

次にKMSの準備を行います。
RDSサービスがKMS鍵のDecryptをする都合、独自のキーポリシーを持つカスタマー管理キーを新規に作成してやる必要があります。

KMSのコンソール画面から新規にキーの作成を開始します。
キータイプは「対称キー」、キーの使用は「暗号化および復号化」を選びます。

詳細オプションでは「KMSオリジン」、「単一リージョンキー」を選んで「次へ」進みます。

キーエイリアスは任意の名前を記入してください。
今回はrds-for-sql-server-self-managed-adとしています。

キー管理のアクセス許可、キー使用のアクセス許可は環境に応じてよしなに設定してください。
(後でRDS用のポリシーを追記します。ここではRDS以外の管理設定をしてください)

最後の確認画面になったらキーポリシーを編集し、既存の内容の最後に以下の定義を追加してやります。

既存のポリシーに追記する

{
    "Sid": "Allow use of the KMS key on behalf of RDS",
    "Effect": "Allow",
    "Principal": {
        "Service": [
            "rds.amazonaws.com"
        ]
    },
    "Action": "kms:Decrypt",
    "Resource": "*"
}

(既存のJSONに 追記 する。置き替えでは無いので注意)

エラー無くキーが作成されればOKです。

3. Secrets Managerの準備

続けてSecrets Managerから新しいシークレットを作成します。
シークレットのタイプは「その他のシークレットタイプ」を選び、

  • CUSTOMER_MANAGED_ACTIVE_DIRECTORY_USERNAME : 専用ユーザーの名前(ここではrdssql@corp.contoso.com)
  • CUSTOMER_MANAGED_ACTIVE_DIRECTORY_PASSWORD : 専用ユーザーの平文パスワード

の2つのキー/値を追加します。
そして暗号化キーに前節で作ったKMSキー(rds-for-sql-server-self-managed-ad)を指定してやります。

シークレット名は任意の名称で構いません。
今回はKMSキーと同じrds-for-sql-server-self-managed-adにしています。

そしてリソースのアクセス許可を以下の様な感じでRDSサービスから許可する様にしてやります。

アカウントIDおよびリージョンは環境に応じて変更

{
    "Version": "2012-10-17",
    "Statement":
    [
        {
            "Effect": "Allow",
            "Principal":
            {
                "Service": "rds.amazonaws.com"
            },
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "*",
            "Condition":
            {
                "StringEquals":
                {
                    "aws:sourceAccount": "xxxxxxxxxxxx(自分のAWSアカウント)"
                },
                "ArnLike":
                {
                    "aws:sourceArn": "arn:aws:rds:ap-northeast-1:xxxxxxxxxxxx:db:*"
                }
            }
        }
    ]
}

その他設定は特に設定不要です。

(キーローテーション不要)

設定値に間違いがないことを確認して「保存」してやります。

エラー無くシークレットが作成されていればOKです。

4. RDSインスタンスの作成

これでやっとRDSインスタンスを作成できます。
本記事ではドメイン参加に必要な部分だけ記載します。
記載のない部分は環境に応じてよしなに設定してください。

今回はRDS for SQL Server 2019 Standard Editionで、エンジンバージョンは最新のSQL Server 2019 15.00.4312.v1を選んでいます。

検証目的なのでインスタンスタイプはdb.t3.xlargeにしました。
その他ネットワーク設定などは環境に応じた設定にしています。

Microsoft SQL Server Windows認証欄で「Microsoft SQL Server Windows認証を有効化」にチェックを付けると新たに「Self-managed Microsoft Active Directory」のオプションが増えているのでこちらを選んでやります。

個別の設定項目は以下の様に記入します。

名称 用途 設定値
Fully qualified domain name 参加ドメイン FQDNで指定 (corp.contoso.com)
Domain organizational unit RDSインスタンス用OU名 識別名で指定 (OU=RDSInstances,DC=corp,DC=contoso,DC=com)
Authorization secret ARN 認証情報シークレット ARNで指定 (rds-for-sql-server-self-managed-adのARN)
Primary DNS Primary DNSサーバー IPアドレスを指定
Secondary DNS Secondary DNSサーバー IPアドレスを指定(入力必須)

今回は検証用でドメインコントローラー(=DNSサーバー)1台構成のためPrimary DNSとSecondary DNSに同じIPアドレスを指定しています。
仕組み上問題ないはずですが実際の本番環境ではちゃんと冗長構成を採る様にしてください。

あとはRDSインスタンスをエラー無く作成できればOKです。

「接続とセキュリティ」タブにディレクトリへの接続状況が表示されます。

Active Directory側から見てもちゃんとRDSInstancesOUにコンピューターオブジェクトが増えています。

5. 接続確認

あとは通常のWindows認証と同じで新しい「ログイン」を作成してやれば良いのですが、SSMSから作成しようとするとエラーになります。

このためSQL文で直接「ログイン」作成する必要があります。
加えて許可するユーザー/グループの指定方法はUPN形式(ユーザー名@ドメイン名)ではなく、Windows 2000以前の形式(ドメイン名\ユーザー名)でないとダメなそうです。

USE [master]
GO
CREATE LOGIN [ドメイン名\ユーザー名] FROM WINDOWS WITH DEFAULT_DATABASE = [master], DEFAULT_LANGUAGE = [us_english];
GO

一旦ログインを作ってしまえばあとの作業はSSMSでも可能です。

(corp\sqlusers = sqlusers@corp.contoso.comというグループでログインを作った場合の一例)

あとは適切なドメインユーザーでRDSインスタンスに接続してやります。

下図は別途用意したyamada@corp.contoso.comというユーザー(sqlusersグループ所属)でWindows認証接続した際の接続情報を表示しています。

認証の種別を表すauth_scheme列の値がNTLMになっているのが見て取れます。

最後に

以上となります。

単純に見えて制限事項が多く、環境構築に必要な作業も多めです。
率直に言ってAWS Managed Microsoft ADを使う方が圧倒的に楽だというのが正直な気持ちです。

AWSのランニングコストを少しでも抑えたい場合や、なんらかの理由でAWS Managed Microsoft ADを採用できない場合の代替案として利用するのが良いのかなと思いました。