Windows設定を管理する

Included in Puppet Enterprise 2017.2.

Windowsサービスの管理

Puppetを使ってWindowsサービスを管理することができます。具体的には、サービスの開始、停止、有効化、無効化、リスト作成、クエリ、設定を行うことが可能です。 これにより、特定のサービスを常に稼働させたり、必要に応じて無効化したりすることができます。

サービスを管理するためのPuppetコードを Puppetマニフェストに記述します。 このマニフェストを適用すると、サービスに加えた変更が適用されます。

サービスの稼働を確定する

Puppetでサービスの稼働を確定するには、以下のコードを使用します。

service { '<service name>':
   ensure => 'running'
}

たとえば、以下のマニフェストコードを使えば、Windows Timeサービスの稼働が確定します。

service { 'w32time':
  ensure => 'running'
}

サービスを停止する

サービスの無効化は、サービスの稼働と同じくらい簡単です。 サービスを無効化するPuppetコードは以下のとおりです。

service { '<service name>':
   ensure => 'stopped',
   enable => 'false'
}

このコードは、ディスクデフラグサービスの無効化など、サービスパフォーマンスに悪影響を与える可能性があるケースで役立ちます。

service { 'defragsvc':
  ensure => 'stopped',
  enable => 'false'
}

マニフェストの変更を適用する別の方法

マニフェストを用いて設定の変更を適用する方法に加えて、Puppetでは、puppet resourceコマンドラインツールを用いてシステム状態を調べる機能が提供されています。このプロセス中にPuppetコードが生成されます。

タスクのスケジューリング

Windowsでは多くの場合、ルーチンのシステムメンテナンスを実施するために、タスクの定期的なスケジューリングが必要となります。 たとえば、ネットワーク上の別のシステムとのファイルの同期、別のディスクへのバックアップの実施、SQLサーバーでのログまたはインデックスメンテナンスの実施などが必要となることがあります。 Puppetで定期的なタスクをスケジューリングしたり、実行したりすることができます。 以下の例では、ファイルを定期的に削除する方法を説明します。

ファイルを再帰的に削除する

ファイルの再帰的な削除は、便利なタスクです。 以下の簡単なコードを使うと、毎日午前8時にすべてのファイルがC:\Windows\Tempから再帰的に削除されます。

scheduled_task { 'Purge global temp files':
   ensure    => present,
   enabled   => true,
   command   => 'c:\\windows\\system32\\cmd.exe',
   arguments => '/c "del c:\\windows\\temp\\*.* /F /S /Q"',
   trigger   => {
   schedule   => daily,
   start_time => '08:00',
  }
}

Puppetでこのタスクを管理するように設定すると、指定したタスクがタスクスケジューラに追加されます。

windows task scheduler

指定した時間に毎日実行するといったタスクのほか、スケジュール設定タスクリソースではさらに高度なスケジューリング機能も数多くサポートしているため、スケジュールをより細かく設定することも可能です。

たとえば、上述のタスクを、2時間ごとにディスククリーンアップを実行するように変更するには、トリガーの定義を以下のように修正します。

scheduled_task { 'Purge global temp files every 2 hours':
   ensure  => present,
   enabled => true,
   command   => 'c:\\windows\\system32\\cmd.exe',
   arguments => '/c "del c:\\windows\\temp\\*.* /F /S /Q"',
   trigger => [{
      day_of_week => ['mon', 'tues', 'wed', 'thurs', 'fri'],
      every => '1',
      minutes_interval => '120',
      minutes_duration => '1440',
      schedule => 'weekly',
      start_time => '07:30'
   }],
  user => 'system',
}

タスクスケジューラのGUIに、このタスクに対応する定義が表示されます。

scheduler edit window

管理者アカウントの管理

多くの場合、Windows管理者パスワードをWindowsデプロイ全体で標準化する必要が生じます。 Puppetを使うと、これを簡単に行うことができます。

user { 'Administrator':
   ensure => present,
   password => 'yabbadabba'
}

マニフェストに使用するパスワードを安全に保護する方法については、この入門レベルの内容では扱いませんが、一般的にこの問題の解決には、ここで述べるキー/値参照ツールであるHieraとeyamlが使用されます。 この解決策では、パスワード値を安全に保存できるだけでなく、パラメータ化して再利用することもできます。これによりWindowsマシンネットワーク全体でパスワードローテーションポリシーを簡単に導入することが可能になります。

ユーザとグループの管理

Puppetを使えば、ローカルグループおよびユーザアカウントを作成することができます。 個別に許可が必要なアプリケーションを切り離す際には、多くの場合、ローカルのユーザーアカウントが必要となります。

異なるアカウントを使用するアプリを設定する

ASP.NETアプリの設定では、デフォルトの Network Serviceとは異なるアカウントを使用する設定が必要となることがあります。 以下の例では、架空のアカウント定義を示しています。

user { 'aspnet_banking_app':
   ensure          => present,
   managehome      => true,
   comment         => 'ASP.NET Service account for Banking application',
   password        => 'banking_app_password',
   groups          => ['IIS_IUSRS', 'Users'],
   auth_membership => 'minimum',
   notify          => Exec['regiis_aspnet_banking_app']
}

exec { 'regiis_aspnet_banking_app':
   path        => 'c:\\windows\\Microsoft.NET\\Framework\\v4.0.30319',
   command     => 'aspnet_regiis.exe -ga aspnet_banking_app',
   refreshonly => true
}

この例では、適切なグループ内でユーザを作成しています。また、ユーザ作成後にASP.NET IIS登録コマンドを実行し、ファイルパーミッションが正しいことを確認しています。

iis users

ユーザリソースに関しては以下の点に注意が必要です。

  • managehomeは、ユーザのディスク上にホームディレクトリを作成するように設定されます。
  • auth_membershipminimumに設定します。このように設定すると、aspnet_banking_appユーザはIIS_IUSRSおよびUsersグループに確実に含まれますが、ユーザが含まれるその他のグループからそのユーザが削除されることはありません。
  • notifyは当該ユーザについて設定し、refreshonlyexecについて設定します。これにより、Puppetはaspnet_banking_appが作成または変更されたときにのみaspnet_regiis.exeを実行します。

ローカルグループを管理する

ローカルグループの管理も可能です。 たとえば、ドメイン管理者グループに存在しないドメインユーザまたはグループをローカル管理者グループに追加する場合は、以下のPuppetコードを使用できます。

group { 'Administrators':
   ensure  => 'present',
   members => ['DOMAIN\\User'],
   auth_membership => false
}

このケースでは、auth_membershipをfalseに設定しています。これにより、DOMAIN\Userは管理者グループに確実に含まれますが、管理者に含まれる可能性のある他のアカウントが削除されることはありません。

usergroups属性とgroupmembers属性については、いずれもSID値を使用できる点に留意してください。たとえば、よく知られている管理者用SIDのS-1-5-32-544などを使用できます。

任意のPowerShellコードの実行

一部のWindowsメンテナンスタスクを実行するには、Windows Management Instrumentation(WMI)を使用する必要があります。WMIメソッドを利用するには、PowerShellがもっとも有効な方法となります。 Puppetには、任意のPowerShellコードを実行する場合に使用できる特別なモジュールがあります。

Windowsドライブインデックスを無効にする

Windowsドライブインデックスはサーバーのディスクパフォーマンスに悪影響を与える可能性があるため、Windowsメンテナンスタスクでは、一般的に無効化されています。

$drive = 'C:'

exec { 'disable-c-indexing':
   provider  => powershell,
   command   => "\$wmi_volume = Get-WmiObject -Class Win32_Volume -Filter 'DriveLetter=\"${drive}\"'; if (\$wmi_volume.IndexingEnabled -ne \$True) { return }; \$wmi_volume | Set-WmiInstance -Arguments @{IndexingEnabled = \$False}",
   unless    => "if ((Get-WmiObject -Class Win32_Volume -Filter 'DriveLetter=\"${drive}\"').IndexingEnabled) { exit 1 }",
}

オブジェクトエディタのウィンドウで結果を見ることができます。

windows maintenance

Windows内蔵のWBEMTestツールを使ってこのマニフェストを実行すると、IndexingEnabledFALSEに設定され、望ましい挙動が得られます。

このexecがいくつかの重要な属性を決定する点に留意してください。

  • プロバイダはPowerShellを使用するように設定されます(これはモジュールに依存します)。
  • commandにはインラインPowerShellが含まれるため、適切にエスケープする必要があります。たとえば、$が前に付くPowerShell変数は、 \$としてエスケープする必要があります。
  • unless属性は、Puppetのべき等性を確保するために設定します。べき等性は、Puppetを用いたリソース管理の鍵を握る特性です。リソースがすでにあるべき状態になっている場合は、Puppetはリソース状態を修正するコマンドを実行しません。

Puppetテンプレートを用いてPuppetコード管理を効率化する

先のセクションで述べたように、インラインPowerShellコードは役に立ちますが、そうしたコードは読み取りやメンテナンスが難しいことがあります。特に、エスケープルールを扱う際には困難が伴います。 マルチラインスクリプトを実行する場合は、代わりにPuppetテンプレートを使用することを推奨します。 以下の例では、テンプレートを使って、Windowsドライブインデックスを無効化するコードを構成する方法を説明します。 詳細については、Puppet言語リファレンスの「Puppetテンプレート」を参照してください。

$drive = 'C:'

exec { 'disable-c-indexing':
  command   => template('Disable-Indexing.ps1.erb'),
  provider  => powershell,


  unless    => "if ((Get-WmiObject -Class Win32_Volume -Filter 'DriveLetter=\"${drive}\"').IndexingEnabled) { exit 1 }",
}

Disable-Indexing.ps1.erbのPowerShellコードは、以下のようになります。

function Disable-Indexing($Drive)
{
  $drive = Get-WmiObject -Class Win32_Volume -Filter "DriveLetter='$Letter'"
  if ($drive.IndexingEnabled -ne $True) { return }
  $drive | Set-WmiInstance -Arguments @{IndexingEnabled=$False} | Out-Null
}

Disable-Indexing -Drive '<%= @driveLetter %>'

パッケージのインストール - NSClient++の例

Windows上でインストーラを実行してソフトウェアを設定するタスクも、Puppetで効率的に実施できる一般的なタスクの1つです。Puppetを使えば、MSIまたはEXEをベースにしたあらゆるパッケージのインストールに対応することができます。 Windowsホストをモニタリングする場合は、通常、NSClient++をインストールし、計測データをNagiosサーバーに報告できるようにWindowsサーバーを設定します。 NSClient++ 0.4.4.15のダウンロードとインストールには、以下のコードを使用します。

$file = 'NSCP-0.4.4.15-x64.msi'
$url  = "https://github.com/mickem/nscp/releases/download/0.4.4.15/${file}"
$temp = "C:\\Windows\\Temp\\${file}"

exec { 'download_nsclient':
  provider  => powershell,
  # note that Start-BitsTransfer can't handle redirected URLs
  command   => "(New-Object Net.WebClient).DownloadFile(\"${url}\", \"${temp}\")",
  creates   => $temp
}

package { 'NSClient++ (x64)':
  ensure  => '0.4.4.15',
  source  => $temp,
  notify  => Reboot['NSClient_install_reboot']
}

reboot { 'NSClient_install_reboot':
  when => refreshed
}

インストールしたアプリをコントロールパネルでチェックすると、予想どおり、インストール済みアプリとしてNSClient++ 0.4.4.15が表示されているはずです。

このマニフェストについては、以下の点に注意が必要です。

  • 先ほどの例と同様、PowerShellプロバイダは、NSClient++インストーラをダウンロードするためにPuppetがPowerShellを呼び出しできるように設定されます。
  • execcreates属性を使用して、Puppet ではインストーラのダウンロードとキャッシュが1回だけ行われるようにします。
  • パッケージリソースでは、ensureの値にパッケージの正確なバージョンを使用します。また、NSClient++ (x64) のリソース名が、インストーラの指定と正確に一致している必要があります。これにより、WindowsにインストールされたアプリをPuppetでチェックできるようになり、NSClient++インストーラが不必要に動作しないよう防ぐことができます。
  • NSClient++のインストール後に、マニュアルリブートが追加されています。これは、PuppetがMSIインストールを開始したときにだけ生じます。ソフトウェアをインストールするとWindowsのリブートが必要になることがあるため、この項目はデモンストレーションのみの目的でこの例に追加されています。Puppetはagent実行の途中でリブートするように指示されています。これにより、Puppetはシャットダウンし、リブート後は中断したところから処理を再開します。この手順では、リブートモジュールもインストールする必要がある点に注意してください。詳細な情報とリブートモジュールは、Forgeで入手可能です

一般的な状況下では、インストール可能なパッケージは安全な内部ネットワークに保存され、ChocolateyフィードまたはローカルSMBシェアからアクセスされます。 わかりやすく独立した例として、このマニフェストでは、NSClient++クライアントをダウンロードし、その後でインストールを実行しています。

↑ Back to top