備考欄に感想を書くタイプのエンジニア

それで出世が遅れ(ry

PowerShell でフォレストの信頼を作成する

※これは PowerShell Advent Calendar 2014: ATND 9 日目の記事です。


昨今進化が目覚ましく、頻繁に話題を目にするようになった PowerShell ですが、Micorosft の製品を利用/運用しているといまだ PowerShell で簡単に実行できないことがいろいろあることに気づく方も多いのではないかと思います(簡単にとい言うのはいわゆる"動詞-名詞" 形式の命名規則に基づいたコマンドレットの実行のことです)。

今回はその中のうち、フォレストの信頼を PowerShell で実行する方法を紹介しようと思います。ご存知かもしれませんが Active Directory の信頼を作成する方法としては GUINetdom コマンドレットがあります。個人の観測範囲内では Netdom すらあまり使われているのを見たことはなく GUI とスクリーン ショットのコンボを決めているのが大半かなと思います。。。

それで、まずマウスでポチポチするのはやめましょうか、と考えたときにじゃあ Netdom を使いましょうか、と思うのですが

Netdom cannot be used to create a forest trust between two AD DS forests. To create a cross forest trust between two AD DS forests, you can either use a scripting solution or the Active Directory Domains and Trusts snap-in. (TechNet | Netdom trust)

要するにフォレスト間の信頼を作成するのに Netdom は使えません。そんな馬鹿な、誰か反論を。ということで残念ながら現時点では PowerShell にもそれを実現するコマンドレットは存在しません。

  • Get-ADForest で、実行した AD フォレストの現時点の情報を取得する→わかる。
  • Get-ADTrust で、実行したドメインにおける現時点の信頼されたドメイン オブジェクトの情報を取得する→わかる。
  • Get-ADForest があるということは New-ADTrustCreate-ADTrust で、特定のドメインもしくはフォレストの間に信頼を作成できそうなのにそういうコマンドレットがない→?!

とは言え、ないものは仕方がありません。幸い PowerShell では .NET Framework を利用できます。利用できますというか PowerShell はいわば .Net Framework アプリケーションですので、今回は不本意(?)ですがその機能を明示的に使っていきたいと思います。

まずどこからか [System.DirectoryServices.ActiveDirectory] 名前空間Forest クラス見つけ出します。msdnForest メソッドを確認してみると CreateLocalSideOfTrustRelationship というメンバーがあります。"Creates the local side of a trust relationship with the specified forest." と書いてあるのでちょうどよさそうです。

一応 PowerShell 上でも確認してみると

PS > $sample = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()

PS > $sample | Get-Member


   TypeName: System.DirectoryServices.ActiveDirectory.Forest

Name                               MemberType Definition                                            
----                               ---------- ----------                                            
CreateLocalSideOfTrustRelationship Method     void CreateLocalSideOfTrustRelationship(string targ...
CreateTrustRelationship            Method     void CreateTrustRelationship(System.DirectoryServic...
DeleteLocalSideOfTrustRelationship Method     void DeleteLocalSideOfTrustRelationship(string targ...
DeleteTrustRelationship            Method     void DeleteTrustRelationship(System.DirectoryServic...
Dispose                            Method     void Dispose(), void IDisposable.Dispose()            
Equals                             Method     bool Equals(System.Object obj)                        
FindAllDiscoverableGlobalCatalogs  Method     System.DirectoryServices.ActiveDirectory.GlobalCata...
FindAllGlobalCatalogs              Method     System.DirectoryServices.ActiveDirectory.GlobalCata...
FindGlobalCatalog                  Method     System.DirectoryServices.ActiveDirectory.GlobalCata...
GetAllTrustRelationships           Method     System.DirectoryServices.ActiveDirectory.TrustRelat...
GetHashCode                        Method     int GetHashCode()                                     
GetSelectiveAuthenticationStatus   Method     bool GetSelectiveAuthenticationStatus(string target...
GetSidFilteringStatus              Method     bool GetSidFilteringStatus(string targetForestName)   
GetTrustRelationship               Method     System.DirectoryServices.ActiveDirectory.ForestTrus...
GetType                            Method     type GetType()                                        
RaiseForestFunctionality           Method     void RaiseForestFunctionality(System.DirectoryServi...
RepairTrustRelationship            Method     void RepairTrustRelationship(System.DirectoryServic...
SetSelectiveAuthenticationStatus   Method     void SetSelectiveAuthenticationStatus(string target...
SetSidFilteringStatus              Method     void SetSidFilteringStatus(string targetForestName,...
ToString                           Method     string ToString()                                     
UpdateLocalSideOfTrustRelationship Method     void UpdateLocalSideOfTrustRelationship(string targ...
UpdateTrustRelationship            Method     void UpdateTrustRelationship(System.DirectoryServic...
VerifyOutboundTrustRelationship    Method     void VerifyOutboundTrustRelationship(string targetF...
VerifyTrustRelationship            Method     void VerifyTrustRelationship(System.DirectoryServic...
ApplicationPartitions              Property   System.DirectoryServices.ActiveDirectory.Applicatio...
Domains                            Property   System.DirectoryServices.ActiveDirectory.DomainColl...
ForestMode                         Property   System.DirectoryServices.ActiveDirectory.ForestMode...
GlobalCatalogs                     Property   System.DirectoryServices.ActiveDirectory.GlobalCata...
Name                               Property   string Name {get;}                                    
NamingRoleOwner                    Property   System.DirectoryServices.ActiveDirectory.DomainCont...
RootDomain                         Property   System.DirectoryServices.ActiveDirectory.Domain Roo...
Schema                             Property   System.DirectoryServices.ActiveDirectory.ActiveDire...
SchemaRoleOwner                    Property   System.DirectoryServices.ActiveDirectory.DomainCont...
Sites                              Property   System.DirectoryServices.ActiveDirectory.ReadOnlySi...

大丈夫そうです。ちょっと途切れてしまっていますが、SyntaxCreateLocalSideOfTrustRelationship(string targetForestName,TrustDirection direction,string trustPassword) となっていますので、例えば一方向:出力の信頼を作成する場合、

$TargetForestName = "Domain.Name"
$TrustPassword = "H0gehQ83"
$TrustDirection = "Outbound"
$Forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$Forest.CreateLocalSideOfTrustRelationship($TargetForestName,$TrustDirection,$TrustPassword)

という、なんともすっきりしないコマンドレットを実行することで信頼の作成が可能です。本当に構成ができているのか確認もしておきたいですよね。では、GUI における [検証] ボタンを押すのと同じように検証をしてみます。

PS > $forest.VerifyOutboundTrustRelationship($TargetForestName)

PS >

何も出力されません。これで大丈夫なのですが、念のため誤ったドメイン名を変数に入力するとこのようなエラーになります。

PS > $fakeTargetForestName = "contoso.com"

PS > $forest.VerifyOutboundTrustRelationship($fakeTargetForestName)
Exception calling "VerifyOutboundTrustRelationship" with "1" argument(s): "A forest trust relationship does not exist 
between "Domain.Name" and "contoso.com"."
At line:1 char:1
+ $forest.VerifyOutboundTrustRelationship($fakeTargetForestName)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ActiveDirectoryObjectNotFoundException
 

PS > 

このように出力されると信頼の作成に失敗していることがよくわかります()一応、信頼の作成ができている状態だと Get-ADTrust のような形で現在構成されている信頼関係から状態を確認することもできますので、確認してみてもいいのではないでしょうか。こんな感じですね。

PS > Get-ADTrust -Filter * | Format-Table -Property Direction,Name,ObjectClass,TrustAttributes -AutoSize

Direction Name                    ObjectClass   TrustAttributes
--------- ----                    -----------   ---------------
 Outbound Domain.Name             trustedDomain               8
 Outbound hogehoge.tokyo          trustedDomain               4

ちなみに今回の記事を書くベースになった Automate Forest trust creation に記載がある通り、双方のフォレストの管理者権限をもつアカウントの情報を持っている場合は PowerShell においてもまたちょっと違った方法で信頼を作成する形となります(内容自体は GUI で実施するときと同じです)。