
RDS for SQL ServerでKerberos認証を使う条件について
This article was published more than one year ago. Please be aware that the information may be outdated.
しばたです。
前回の記事でRDS for SQL ServerがセルフマネージドなActive Directoryドメインに参加した場合はNTLM認証
のみ可能な旨を説明しました。
記事を書いている途中で「従来のAWS Managed Microsoft ADドメインに参加した場合はどうだっけ?詳しく調べたこと無いな。」となったので実際に調べてみました。
SQL ServerでKerberos認証が使われる条件
RDS for SQL Serverの話をするまえにSQL Serverの仕様を確認しておきます。
SQL ServerでKerberos認証が使われる条件は以下のドキュメントに記載されています。
SQL Server で Kerberos 認証を使用するには、次の両方の条件が満たされる必要があります。
クライアント コンピューターとサーバー コンピューターが、同じ Windows ドメインまたは信頼関係のあるドメインの一部であることが必要です。
SPN (サービス プリンシパル名) は、Windows ドメインのキー配布センターの役割を担う Active Directory に登録されることが必要です。 SPN は、登録後に、SQL Server インスタンス サービスを起動した Windows アカウントに対してマップされます。 SPN 登録がまだ実行されていないか失敗した場合、Windows セキュリティ レイヤーでは SPN に関連するアカウントを決定することができず、Kerberos 認証は使用されません。
重要なのは後者のほうで「適切なSPNが登録されていなければKerberos認証は使われずNTLM認証にフォールバックする」仕様となっています。
RDSは通常独自のDNSエンドポイント(rds.amazonaws.com
なホスト名)に対して接続します。
すると「そもそも適切なSPNが登録されていないのでは?常にNTLM認証しかしないのでは?」という疑問が湧いてきます。
AWS Managed Microsoft AD ドメインに参加した場合
ということで、まずはAWS Managed Microsoft AD環境を用意してRDSインスタンスをドメインに参加させ挙動を確認してみました。
新規にcorp2.contoso.com
ドメイン[1]を用意し、RDS for SQL Serverインスタンスを参加させてます。併せて管理用EC2インスタンスも用意しておきました。
(mydb2がAWS Managed Microsoft AD参加のインスタンス。mydbは前回使用したセルフマネージドAD参加インスタンス。)
この状態で管理用EC2インスタンスからSPNの登録状況を調査すると以下の様になりました。
# SQL Server (MSSQLSvc) 用SPNを検索
PS C:\> setspn -T * -F -Q MSSQLSvc/*
フォレスト DC=corp2,DC=contoso,DC=com を確認しています
CN=EC2AMAZ-OI56D18,OU=RDS,OU=AWS Reserved,DC=corp2,DC=contoso,DC=com
MSSQLSvc/mydb2.corp2.contoso.com:1433
MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com:1433
MSServerClusterMgmtAPI/EC2AMAZ-OI56D18
MSServerClusterMgmtAPI/EC2AMAZ-OI56D18.corp2.contoso.com
MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com
TERMSRV/EC2AMAZ-OI56D18
TERMSRV/EC2AMAZ-OI56D18.corp2.contoso.com
RestrictedKrbHost/EC2AMAZ-OI56D18
HOST/EC2AMAZ-OI56D18
RestrictedKrbHost/EC2AMAZ-OI56D18.corp2.contoso.com
HOST/EC2AMAZ-OI56D18.corp2.contoso.com
RDS for SQL Serverインスタンスの実体(EC2AMAZ-OI56D18
)にSPNの登録があることが分かります。
このインスタンスに絞って検索すると以下の結果になります。
# EC2AMAZ-OI56D18 に絞ってSPNを表示
PS C:\> setspn -L EC2AMAZ-OI56D18
次の項目に登録されている CN=EC2AMAZ-OI56D18,OU=RDS,OU=AWS Reserved,DC=corp2,DC=contoso,DC=com:
MSSQLSvc/mydb2.corp2.contoso.com:1433
MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com:1433
MSServerClusterMgmtAPI/EC2AMAZ-OI56D18
MSServerClusterMgmtAPI/EC2AMAZ-OI56D18.corp2.contoso.com
MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com
TERMSRV/EC2AMAZ-OI56D18
TERMSRV/EC2AMAZ-OI56D18.corp2.contoso.com
RestrictedKrbHost/EC2AMAZ-OI56D18
HOST/EC2AMAZ-OI56D18
RestrictedKrbHost/EC2AMAZ-OI56D18.corp2.contoso.com
HOST/EC2AMAZ-OI56D18.corp2.contoso.com
インスタンスの実体となる
MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com:1433
以外に
MSSQLSvc/mydb2.corp2.contoso.com:1433
という行があることが分かります。
これはRDS for SQL Server側で専用のホスト名[DB識別子].[ドメインFQDN]
をエイリアス(CNAME)として提供しているものになります。
# CNAMEの実体は EC2AMAZ-OI56D18.corp2.contoso.com
PS C:\> nslookup mydb2.corp2.contoso.com
サーバー: corp2.contoso.com
Address: 10.0.21.30
名前: EC2AMAZ-OI56D18.corp2.contoso.com
Address: 10.0.21.15
Aliases: mydb2.corp2.contoso.com
AWSのドキュメントでは自分で作る様な書き方をしていますが、実際には自動で作成されていました。
Kerberos-based authentication requires that the endpoint be the customer-specified host name, a period, and then the fully qualified domain name (FQDN). For example, the following is an example of an endpoint you might use with Kerberos-based authentication. In this example, the SQL Server DB instance host name is ad-test and the domain name is corp-ad.company.com.
当然RDSのDNSエンドポイントに対するSPNはありません。
このため以下の結果になることが予想されます。
- RDSのエンドポイント(
mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com
) → NTLM認証 - エイリアスのDNS名 (
mydb2.corp2.contoso.com
) → Kerberos認証 - インスタンスの実体 (
EC2AMAZ-OI56D18.corp2.contoso.com
) → Kerberos認証
それぞれのホスト名に対し接続した結果は以下の通りです。
# sqlcmdコマンドで接続確認
sqlcmd -S mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com -H "EC2 (rds.amazonaws.com)"
sqlcmd -S mydb2.corp2.contoso.com -H "EC2 (mydb2.corp2.contoso.com)"
sqlcmd -S EC2AMAZ-OI56D18.corp2.contoso.com -H "EC2 (EC2AMAZ-OI56D18.corp2.contoso.com)"
(識別しやすい様にホスト名-H
を個別に変えて接続)
(それぞれのセッション情報を取得)
ばっちり予想通りの結果となりました。
セルフマネージドなActive Directoryドメインに参加した場合
こちらは前回記事の環境corp.contoso.com
ドメインとRDSインスタンスをそのまま使います。
ドメインコントローラーからSPNの登録状況を調査すると以下の様になりました。
# SQL Server (MSSQLSvc) 用SPNを検索
PS C:\> setspn -T * -F -Q MSSQLSvc/*
フォレスト DC=corp,DC=contoso,DC=com を確認しています
CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com
# ・・・省略・・・
CN=EC2AMAZ-1K2JSBE,OU=RDSInstances,DC=corp,DC=contoso,DC=com
# ・・・省略・・・
CN=EC2AMAZ-6HMJA86,OU=RDSInstances,DC=corp,DC=contoso,DC=com
# ・・・省略・・・
CN=EC2AMAZ-FD531AP,OU=RDSInstances,DC=corp,DC=contoso,DC=com
# ・・・省略・・・
CN=EC2AMAZ-PN76CIR,OU=RDSInstances,DC=corp,DC=contoso,DC=com
# ・・・省略・・・
CN=EC2AMAZ-QRTV9CT,OU=RDSInstances,DC=corp,DC=contoso,DC=com
# ・・・省略・・・
検証作業で何度もRDSインスタンスの停止・再起動を繰り返したためその分すべての内容が残っていました。
(ゴミとなったコンピューターオブジェクトも残っている...)
この時点でのインスタンスの実体はEC2AMAZ-06CNSE2
のため、対象を絞った結果は以下の通りです。
# EC2AMAZ-06CNSE2 に絞ってSPNを表示
# 一件SPNはあるが、ポート番号の記載が無い
PS C:\> setspn -L EC2AMAZ-06CNSE2
次の項目に登録されている CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com:
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2
MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2.corp.contoso.com
TERMSRV/EC2AMAZ-06CNSE2
TERMSRV/EC2AMAZ-06CNSE2.corp.contoso.com
WSMAN/EC2AMAZ-06CNSE2
WSMAN/EC2AMAZ-06CNSE2.corp.contoso.com
RestrictedKrbHost/EC2AMAZ-06CNSE2
HOST/EC2AMAZ-06CNSE2
RestrictedKrbHost/EC2AMAZ-06CNSE2.corp.contoso.com
HOST/EC2AMAZ-06CNSE2.corp.contoso.com
セルフマネージドなADではCNAMEの自動作成は行われません。
また、AWS Managed Microsoft AD環境と同様にインスタンスの実体となる
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
の記述はありますが、AWS Managed Microsoft AD環境と異なりポート番号は記載されていません。
ドキュメントによればポート番号が無いものはTPC以外のプロトコル用とのことで、これはダメな予感がします。
TCP 以外のプロトコルが使用される場合に、既定のインスタンスに対してプロバイダーが生成する既定の SPN。<FQDN> は、完全修飾ドメイン名です。
ということで、予想としては
- RDSのエンドポイント(
mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com
) → NTLM認証 - インスタンスの実体 (
EC2AMAZ-06CNSE2.corp.contoso.com
) → NTLM認証
になり、実際結果もその通りでした。
sqlcmd -S mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com -H "ADDS (rds.amazonaws.com)"
sqlcmd -S EC2AMAZ-06CNSE2.corp.contoso.com -H "ADDS (EC2AMAZ-06CNSE2.corp.contoso.com)"
(識別しやすい様にホスト名-H
を個別に変えて接続)
(それぞれのセッション情報を取得)
AWSの言う通りセルフマネージドなADに参加した場合は常にNTLM認証が使われます。
結果まとめ
ここまでの結果を表にまとめました。
ディレクトリ種別 | 接続先ホスト名 | 認証方式 | 備考 |
---|---|---|---|
AWS Managed Microsoft AD | RDSのDNSエンドポイント([DB識別子].xxxxxx.[リージョン名].rds.amazonaws.com) | NTLM認証 | SPN無し |
AWS Managed Microsoft AD | エイリアスのDNS名 ([DB識別子].[ドメインFQDN]) | Kerberos認証 | AWS Managed Microsoft ADが自動で用意してくれるCNAME |
AWS Managed Microsoft AD | 実体のEC2インスタンス ([EC2AMAZ-XXXXXXX].[ドメインFQDN]) | Kerberos認証 | 非推奨 |
セルフマネージドなAD | RDSのDNSエンドポイント([DB識別子].xxxxxx.[リージョン名].rds.amazonaws.com) | NTLM認証 | SPN無し |
セルフマネージドなAD | 実体のEC2インスタンス ([EC2AMAZ-XXXXXXX].[ドメインFQDN]) | NTLM認証 | 非推奨 |
AWS Managed Microsoft AD環境でエイリアスのDNS名と実体となるEC2ホスト名を指定したときだけKerberos認証が使えます。
ただし、実体となるEC2ホスト名は結構頻繁に変わりうるので運用環境での利用はお勧めできません。
(どうやらRDSの起動・停止の都度変わっている、EC2インスタンスがすげ替えられる様な挙動をしている...)
エイリアスのDNS名は実体のEC2インスタンスが切り替わった場合でも追従して更新されたのでこちらを使う様にしてください。
余談 : むりやりSPNを設定してみる (非サポート/無保証)
ここまでくると「セルフマネージドなAD環境でも自分でSPNを設定すればKerberos認証できるのでは?」と考えるのは必然です。
ということで実際やってみました。
インスタンスの実体に対するSPNを追加
まずはインスタンスの実体EC2AMAZ-06CNSE2.corp.contoso.com
に対するSPNを追加してみます。
# ポート番号付きのSPNを登録する
setspn -S MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433 EC2AMAZ-06CNSE2
実行結果はこの様になり、ポート番号付きの行が増えました。
PS C:\> setspn -S MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433 EC2AMAZ-06CNSE2
ドメイン DC=corp,DC=contoso,DC=com を確認しています
CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com の ServicePrincipalNames を登録しています
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433
更新されたオブジェクト
PS C:\> setspn -L EC2AMAZ-06CNSE2
次の項目に登録されている CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com:
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2
MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2.corp.contoso.com
TERMSRV/EC2AMAZ-06CNSE2
TERMSRV/EC2AMAZ-06CNSE2.corp.contoso.com
WSMAN/EC2AMAZ-06CNSE2
WSMAN/EC2AMAZ-06CNSE2.corp.contoso.com
RestrictedKrbHost/EC2AMAZ-06CNSE2
HOST/EC2AMAZ-06CNSE2
RestrictedKrbHost/EC2AMAZ-06CNSE2.corp.contoso.com
HOST/EC2AMAZ-06CNSE2.corp.contoso.com
これはいけそうな気がします。
この状態で接続確認してみるとKerberos認証
で接続してくれました。
いい感じです。
ちなみに追加したSPNを削除する際は以下のコマンドを実行します。
# setspn -D でSPNを削除
setspn -D MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433 EC2AMAZ-06CNSE2
CNAMEレコードも追加してみた
続けてDNSにCNAMEレコードを追加してAWS Managed Micrsoft ADと同様のことをやっていきます。
今回はrdssql.corp.contoso.com
というエイリアスを作ってみます。
# 結果はこんな感じ
PS C:\> nslookup rdssql
サーバー: localhost
Address: ::1
名前: EC2AMAZ-06CNSE2.corp.contoso.com
Address: 10.0.21.239
Aliases: rdssql.corp.contoso.com
さらにこのホスト名に対するSPNを作成します。
# rdssql.corp.contoso.comに対するSPNを追加
setspn -S MSSQLSvc/rdssql.corp.contoso.com:1433 EC2AMAZ-06CNSE2
最終的な結果は以下の通りです。
PS C:\> setspn -S MSSQLSvc/rdssql.corp.contoso.com:1433 EC2AMAZ-06CNSE2
ドメイン DC=corp,DC=contoso,DC=com を確認しています
CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com の ServicePrincipalNames を登録しています
MSSQLSvc/rdssql.corp.contoso.com:1433
更新されたオブジェクト
PS C:\> setspn -L EC2AMAZ-06CNSE2
次の項目に登録されている CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com:
MSSQLSvc/rdssql.corp.contoso.com:1433
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2
MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2.corp.contoso.com
TERMSRV/EC2AMAZ-06CNSE2
TERMSRV/EC2AMAZ-06CNSE2.corp.contoso.com
WSMAN/EC2AMAZ-06CNSE2
WSMAN/EC2AMAZ-06CNSE2.corp.contoso.com
RestrictedKrbHost/EC2AMAZ-06CNSE2
HOST/EC2AMAZ-06CNSE2
RestrictedKrbHost/EC2AMAZ-06CNSE2.corp.contoso.com
HOST/EC2AMAZ-06CNSE2.corp.contoso.com
これでrdssql.corp.contoso.com
に対して接続してやるとKerberos認証
になりました。
sqlcmd -S rdssql.corp.contoso.com -H "ADDS (rdssql.corp.contoso.comm)"
RDSのDNSエンドポイントにSPNを追加してみた
最後にRDSのDNSエンドポイントに対するSPNを追加してみます。
# RDSのDNSエンドポイントに対するSPNを追加
setspn -S MSSQLSvc/mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433 EC2AMAZ-06CNSE2
出来ないと思っていたのですが実際やってみると可能でした。
PS C:\> setspn -S MSSQLSvc/mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433 EC2AMAZ-06CNSE2
ドメイン DC=corp,DC=contoso,DC=com を確認しています
CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com の ServicePrincipalNames を登録しています
MSSQLSvc/mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433
更新されたオブジェクト
PS C:\> setspn -L EC2AMAZ-06CNSE2
次の項目に登録されている CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com:
MSSQLSvc/mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433
MSSQLSvc/rdssql.corp.contoso.com:1433
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433
MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2
MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2.corp.contoso.com
TERMSRV/EC2AMAZ-06CNSE2
TERMSRV/EC2AMAZ-06CNSE2.corp.contoso.com
WSMAN/EC2AMAZ-06CNSE2
WSMAN/EC2AMAZ-06CNSE2.corp.contoso.com
RestrictedKrbHost/EC2AMAZ-06CNSE2
HOST/EC2AMAZ-06CNSE2
RestrictedKrbHost/EC2AMAZ-06CNSE2.corp.contoso.com
HOST/EC2AMAZ-06CNSE2.corp.contoso.com
そしてKerberos認証
による接続もできました。
sqlcmd -S mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com -H "ADDS (rds.amazonaws.com)"
意外となんとかなるものです。
なお、AWS Managed Microsoft AD環境で同様の行為をした場合は権限エラーになります。
# AWS Managed Microsoft AD環境では権限が足りず同様の行為は行えない
PS C:\> setspn -S MSSQLSvc/mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433 EC2AMAZ-OI56D18
ドメイン DC=corp2,DC=contoso,DC=com を確認しています
CN=EC2AMAZ-OI56D18,OU=RDS,OU=AWS Reserved,DC=corp2,DC=contoso,DC=com の ServicePrincipalNames を登録しています
MSSQLSvc/mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433
アカウント 'CN=EC2AMAZ-OI56D18,OU=RDS,OU=AWS Reserved,DC=corp2,DC=contoso,DC=com' で SPN を割り当てられませんでした。エラー 0x2098/8344 -> この操作を実行するための十分なアクセス権がありません。
最後に
以上となります。
今回の結果からRDS for SQL ServerでKerberos認証を使うのは限定的な条件でのみ可能であることが分かりました。
普段の利用においてあまり意識することが無いかもしれませんが、認証方式に対して厳密な要件がある場合はご注意ください。
corp2なのは前回との対比のため ↩︎