🍣

【PowerShell/ActiveDirectory】ADサーバでスクリプト実行してファイルサーバにOUと同階層構造の共有フォルダを作成!

2025/02/13に公開

どうも!前歯すきっ歯です🦷

ドメインユーザーセキュリティグループを一括作成したので、
今回は共有フォルダを作成してクライアントサーバからの見え方を確認します!
このActiveDirectory(以下ADと呼ぶ)関連の流れは今回が最終回です~

1.本記事について

1.1💪勉強のゴール💪

今回のゴールは以下5点です。

1.2 前提条件

1.2.1 本記事の下準備

次に紹介する「1.2.2 前提条件詳細」と同条件で実施している以下記事の続編です。以下記事を読まなくても本記事は読み進められますが、詳細な前提を知りたい方はご覧ください。

1.2.2 前提条件詳細

以下7点を本記事の前提条件とします。

  1. gapteeth.studyというドメインでADサーバ×2台、ファイルサーバ×1台、クライアントサーバ×1台を作成済みです。
  2. ADサーバはWindowsSever2022のActiveDirectoryを利用しています。
  3. 以下画像のOUの構成を作成済みです。
  4. 各OUに所属するセキュリティグループを作成済みです。それらの名前は「(OU名)-SG」です。
  5. ドメインユーザーを作成し、ユーザー自身が所属するOUにあるセキュリティグループに所属させています。また、自分が所属するOUより下位の階層に所属するユーザーの権限は持つように設定しています。詳しくは本記事の前編をご覧ください。
    https://zenn.dev/gapteeth/articles/9a79aed1267b05
  6. 各サーバはAWSの同プライベートサブネット内で作成しており、各サーバ間は通信ができるようにセキュリティグループを設定しています。

    AD=ADサーバ、FS=ファイルサーバです。
  7. ファイルサーバ内にDドライブを切り出し済みです。

1.3 読者に求める前提知識

IT初心者向けの記事ですが、ADサーバとPowerShellの基礎的な操作をしたことがある前提で記事を書きます。それらに触るのが初めての場合、もしよければ以下の記事を読んでみてください!自分の記事で恐縮ですが、初心者向けの勉強方法の記載をしてあります。

2.知識収集

今回の勉強にあたり調べて分かりやすかったリンク5つをご紹介します。
もしよかったらご覧ください!

2.1 AD関連コマンドを他サーバで実行するできるのか

詳細は後述しますが、AD関連のコマンドをADの役割と機能が入っていないサーバで実行することは難しいみたいです…。OU情報を取得するコマンド(=AD関連のコマンド)がファイルサーバで実行できないので、今回はADサーバでスクリプトを実行しています。

2.2 他サーバで実行したスクリプトから共有フォルダ作成

2.1に伴い、ADサーバ(=ファイルサーバ以外の他サーバ)からファイルサーバ上に共有フォルダを作成する方法を調べました。

2.3 CIMセッションについて

2.2の中で記載されていた「CIMとはなんぞや」と思い調べてみました。

2.4 Get-ADOrganizationalUnitのCanonicalNameオプション

今回はこの手法でOU情報を取得します。

2.5 文字列の置き換え方法

2.4の手法でOU情報を取得した後に、それらの情報を共有フォルダのパス指定に使えるように変換しました。

3.作成したスクリプトと大まかな流れ

3.1 スクリプトの大まかな流れ

セキュリティグループ作成の大まかな流れは以下の通りです。

3.2 スクリプト

結論、以下が作成して実行の確認ができたスクリプトです。
スクリプトを細分化して作成の意図を後述していきます。

共有フォルダ作成スクリプト
#ADサーバで実行することが前提

#エラーだったら実行をストップする
$ErrorActionPreference = "Stop"

#ADサーバのPowerShellからフィルサーバのPowershellへの接続----------------------------------------------------------------------------------------
#パスワードをSecureStringに変換
$secPassword = ConvertTo-SecureString "[ドメインのAdministratorのパスワード]" -AsPlainText -Force
#認証情報の生成
$credential = New-Object System.Management.Automation.PSCredential("gapteeth.study\Administrator", $secPassword)
$cim = New-CimSession -ComputerName "FS01" -Credential $credential

#共有フォルダの作成-------------------------------------------------------------------------------------------------------------------------------

#現在のOU情報を取得(OU名を共有フォルダ名とする)
$OUinfo = Get-ADOrganizationalUnit -Filter * -Properties CanonicalName | Select-Object -Property Name,CanonicalName

foreach ($Folderinfo in $OUinfo) {
    #フォルダ作成で使用するパスを定義(ドライブを共有パスで指定するから"D$"を使う)  ★ドメインを"\\FS01\D$"に置換
    $MakePath = $($Folderinfo.CanonicalName).Replace("gapteeth.study", "\\FS01\D$").Replace("/$($Folderinfo.Name)", "").Replace("/", "\")
    #共有フォルダ作成で使用するパスを定義(ドライブをローカルパスで指定するから"D:"を使う) ★ドメインを"D:"に置換
    $SharePath = $($Folderinfo.CanonicalName).Replace("gapteeth.study", "D:").Replace("/", "\")
    #権限を許可するセキュリティグループ名を定義
    $SG = "$($Folderinfo.Name)-SG"
    #対象フォルダの作成
    New-Item -Name $Folderinfo.Name -Path $MakePath -ItemType directory
    #共有フォルダの作成
    New-SmbShare -Name $Folderinfo.Name -Path $SharePath -FullAccess $SG -CimSession $cim
}

4.スクリプト作成の意図

4.1 ADサーバからファイルサーバのPowerShellへ接続できるように認証を行なう。

ファイルサーバへの接続
#ADサーバで実行することが前提
#ADサーバのPowerShellからフィルサーバのPowershellへの接続----------------------------------------------------------------------------------------
#パスワードをSecureStringに変換
$secPassword = ConvertTo-SecureString "[ドメインのAdministratorのパスワード]" -AsPlainText -Force
#認証情報の生成
$credential = New-Object System.Management.Automation.PSCredential("gapteeth.study\Administrator", $secPassword)
$cim = New-CimSession -ComputerName "FS01" -Credential $credential

4.1.1 #ADサーバで実行することが前提

  • AD関連のコマンドはADの役割と機能がないサーバでは実行できない。
    2.1 AD関連コマンドを他サーバで実行するできるのかで紹介しましたが、サーバの役割と機能でADをインストールしていないとAD関連のコマンドが使えません。今回はOU情報を取得するためのGet-ADOrganizationalUnitコマンドを利用したいので、作成するものはファイルサーバ上の共有フォルダですがADサーバのPowerShellから実行します。
    参考までにGet-ADOrganizationalUnitを各サーバで実行するとどうなるのか記載しておきます。⇩
ファイルサーバでの実行結果
Get-ADOrganizationalUnitコマンド
PS C:\Users\administrator.GAPTEETH> Get-ADOrganizationalUnit -Filter "*" -SearchBase "DC=gapteeth,DC=study" -SearchScope Subtree | Select-Object Name,DistinguishedName
Get-ADOrganizationalUnit : 用語 'Get-ADOrganizationalUnit' は、コマンドレット、関数、スクリプト ファイル、または操作可
能なプログラムの名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正
しいことを確認してから、再試行してください。
発生場所 行:1 文字:1
+ Get-ADOrganizationalUnit -Filter "*" -SearchBase "DC=gapteeth,DC=stud ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-ADOrganizationalUnit:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
ADサーバでの実行結果
Get-ADOrganizationalUnitコマンド
PS C:\Users\Administrator> Get-ADOrganizationalUnit -Filter "*" -SearchBase "DC=gapteeth,DC=study" -SearchScope Subtree |
Select-Object Name,DistinguishedName                                                                                  
Name               DistinguishedName
----               -----------------
Domain Controllers OU=Domain Controllers,DC=gapteeth,DC=study
営業部             OU=営業部,DC=gapteeth,DC=study
第1課              OU=第1課,OU=営業部,DC=gapteeth,DC=study
第2課              OU=第2課,OU=営業部,DC=gapteeth,DC=study
総務部             OU=総務部,DC=gapteeth,DC=study
人事課             OU=人事課,OU=総務部,DC=gapteeth,DC=study
経理課             OU=経理課,OU=総務部,DC=gapteeth,DC=study
労務Gr             OU=労務Gr,OU=人事課,OU=総務部,DC=gapteeth,DC=study
採用Gr             OU=採用Gr,OU=人事課,OU=総務部,DC=gapteeth,DC=study
製造部             OU=製造部,DC=gapteeth,DC=study
工場課             OU=工場課,OU=製造部,DC=gapteeth,DC=study
調達課             OU=調達課,OU=製造部,DC=gapteeth,DC=study
社長               OU=社長,DC=gapteeth,DC=study

4.1.2 $cim = New-CimSession -ComputerName "FS01" -Credential $credential

  • ファイルサーバへの認証を行う
    4.1.1の理由からADサーバのPowershellでスクリプトを実行する必要があります。しかし、共有フォルダを設定するNew-SmbShareコマンドは共有フォルダを作成するサーバ上で実行する必要があります。そこで、2.3 CIMセッションについてで紹介した方法を用いてファイルサーバへアクセスしてNew-SmbShareコマンドします。上記$cim = New-CimSession -ComputerName "FS01" -Credential $credentialファイルサーバへアクセスする際の認証部分を行っています。

4.2 共有フォルダの作成

共有フォルダの作成
#共有フォルダの作成-------------------------------------------------------------------------------------------------------------------------------

#現在のOU情報を取得(OU情報を利用して共有フォルダを作成する)
$OUinfo = Get-ADOrganizationalUnit -Filter * -Properties CanonicalName | Select-Object -Property Name,CanonicalName

foreach ($Folderinfo in $OUinfo) {
    #フォルダ作成で使用するパスを定義(ドライブを共有パスで指定するから"D$"を使う)  ★ドメインを"\\FS01\D$"に置換
    $MakePath = $($Folderinfo.CanonicalName).Replace("gapteeth.study", "\\FS01\D$").Replace("/$($Folderinfo.Name)", "").Replace("/", "\")
    #共有フォルダ作成で使用するパスを定義(ドライブをローカルパスで指定するから"D:"を使う) ★ドメインを"D:"に置換
    $SharePath = $($Folderinfo.CanonicalName).Replace("gapteeth.study", "D:").Replace("/", "\")
    #権限を許可するセキュリティグループ名を定義
    $SG = "$($Folderinfo.Name)-SG"
    #対象フォルダの作成
    New-Item -Name $Folderinfo.Name -Path $MakePath -ItemType directory
    #共有フォルダの作成
    New-SmbShare -Name $Folderinfo.Name -Path $SharePath -FullAccess $SG -CimSession $cim
}

4.2.1 $OUinfo = Get-ADOrganizationalUnit -Filter * -Properties CanonicalName | Select-Object -Property Name,CanonicalName

  • 全OU情報を取得
    今回はOUの階層構造と同じ階層構造のフォルダを作成するので、まずOU情報を取得します。それらを置換してフォルダを作成したり、共有設定したりするときのパスとして使います。
    ちなみに、変数格納前のGet-ADOrganizationalUnit -Filter * -Properties CanonicalName | Select-Object -Property Name,CanonicalNameを実行すると以下になります。CanonicalName オプションで取得した情報がどことなくパスの指定に似ていますよね…(?)
OU情報の取得
Get-ADOrganizationalUnitコマンド
PS C:\Users\Administrator> Get-ADOrganizationalUnit -Filter * -Properties CanonicalName | Select-Object -Property Name,CanonicalName

Name               CanonicalName
----               -------------
Domain Controllers gapteeth.study/Domain Controllers
営業部             gapteeth.study/営業部
第1課              gapteeth.study/営業部/第1課
第2課              gapteeth.study/営業部/第2課
総務部             gapteeth.study/総務部
人事課             gapteeth.study/総務部/人事課
経理課             gapteeth.study/総務部/経理課
労務Gr             gapteeth.study/総務部/人事課/労務Gr
採用Gr             gapteeth.study/総務部/人事課/採用Gr
製造部             gapteeth.study/製造部
工場課             gapteeth.study/製造部/工場課
調達課             gapteeth.study/製造部/調達課
社長               gapteeth.study/社長

4.2.2 $MakePath = $($Folderinfo.CanonicalName).Replace("gapteeth.study","\\FS01\D$").Replace("/$($Folderinfo.Name)","").Replace("/","\")

  • フォルダを作成するパスを作成する
    どことなくパス指定と似ているCanonicalName オプションですが、フォルダを作成するパスとの違いが3点ありReplaceメソッドを使ってそれらを解消しています。各.Replaceメソッドでは以下を意図しています。
    .Replace("gapteeth.study","\\FS01\D$")⇒ドメイン部分をサーバとドライブの指定に置換。
    .Replace("/$($Folderinfo.Name)","")⇒フォルダ名は不要なので削除(空白に置換)。
    .Replace("/","\")⇒スラッシュの向きが全て逆なので置換。
    例:第1課のフォルダを作成するとき
    >#本来行いたいパス指定======================
    >\\FS01\D$\営業部
    <#CanonicalNameオプション==================
    <gapteeth.study/営業部/第1課
    

4.2.3 $SharePath = $($Folderinfo.CanonicalName).Replace("gapteeth.study","D:").Replace("/","\")

  • 共有設定するパスを作成する
    共有設定するパスとの違いは2点あり、4.2.2同様にReplaceメソッドを使ってそれらを解消しています。
    .Replaceメソッドでは以下を意図しています。
    .Replace("gapteeth.study","D:")⇒ローカルのDドライブのパスを指定。
    .Replace("/","\")⇒スラッシュの向きが全て逆なので置換。
例:第1課のフォルダの共有設定をするとき
>#本来行いたいパス指定======================
>\\D:\営業部\第1課
<#CanonicalNameオプション==================
<gapteeth.study/営業部/第1課

5.スクリプト作成中の備忘録

5.1 CanonicalNameオプションの出力結果はスラッシュが逆だから要注意

4.2.2などでも記述しましたが、CanonicalNameオプションの出力結果はパス指定で使いたい\とスラッシュが逆です。 最初それに気が付かず下記スクリプトを実行していたところ、フォルダ等ディレクトリは作成できますが、共有設定ではスラッシュが逆向きなので実態のフォルダに共有設定が反映されませんでした。

.Replace("/","\")が抜けたスクリプト
#フォルダ作成で使用するパスを定義(ドライブを共有パスで指定するから"D$"を使う)  ★ドメインを"\\FS01\D$"に置換
$MakePath = $($Folderinfo.CanonicalName).Replace("gapteeth.study","\\FS01\D$").Replace("/$($Folderinfo.Name)","")
#共有フォルダ作成で使用するパスを定義(ドライブをローカルパスで指定するから"D:"を使う) ★ドメインを"D:"に置換
$SharePath = $($Folderinfo.CanonicalName).Replace("gapteeth.study","D:") 


fsmgmt.mscから見た共有設定。スラッシュが逆であることが分かる

上の画像の時に作成されたフォルダ。共有設定は存在するが反映されていない

正しいスクリプトを実行してfsmgmt.mscから見た共有設定。\が入っている

共有設定が反映されている。セキュリティグループの許可設定も正しく入っている。

6.セキュリティグループが有効か確認

6.1 ドメインユーザーがリモデできるようにする

6.1.1 デフォルトではサーバへドメインユーザーがリモデできない

あるドメインユーザーでログインしようとしたところ拒否されてしまいました…。
ドメインのAdministrator以外のユーザーはデフォルトでアクセス拒否されています。

6.1.2 ドメインユーザーの許可設定をする

以下記事が詳しく手順を解説してくださっているので、それに倣い設定します。
https://qiita.com/dan-go/items/63cd5b16387e70257d06

6.1.3 リモデ許可の時に指定する名前はNew-ADUserコマンドのNameオプションで指定したものを使う


Nameを入力してから[名前の確認]を押すと…

読み取ってくれる

それ以外の名前だと…

「名前が見つかりません」と表示される

6.1.4 リモデの時はuserPlincipalNameを使う

色んなところで使う名前が違くて紛らわしいですね…
ADサーバの[ActiveDirectory ユーザーとコンピュータ]で各ユーザーのプロパティを確認すると分かりやすいですが、userPlincipalNameを使ってリモデしましょう!userPlincipalNameオプションで指定する部分に「ユーザーログオン名」と記載があります。

6.2 アクセスして確認する

6.2.1 総務部直下所属(OU=総務部)のユーザーで確認

以下2点確認ができました!

  • 総務部内1番下の階層の労務Grまでアクセスできて、営業部等他の階層へのアクセスは拒否される。
  • アクセス権限がある階層ではファイルの新規作成が可能

    営業部へのアクセスは拒否

    労務Grの階層までアクセスして新規ファイルの作成も可能

6.2.2 採用Gr所属(OU=採用Gr,OU=人事課,OU=総務部)のユーザーで確認

以下2点確認ができました!

  • 人事課より上の階層へはアクセスできない。
  • 採用Grの階層ではファイルの新規作成が可能

    人事課より上の階層にはいけない

    採用Grへのアクセスとファイルの作成が成功!

7.おわりに

技術的に誤った部分、もっとより良い案や考え方があれば遠慮なくコメントで教えていただけると嬉しいです😆よろしくお願いします!

Discussion