<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>wAdmin.ru &#187; Powershell</title>
	<atom:link href="http://blog.wadmin.ru/tag/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.wadmin.ru</link>
	<description>Записки сисадмина</description>
	<lastBuildDate>Sun, 05 Feb 2012 12:00:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>PowerShell модуль GroupPolicy</title>
		<link>http://blog.wadmin.ru/2012/02/powershell-grouppolicy-module/</link>
		<comments>http://blog.wadmin.ru/2012/02/powershell-grouppolicy-module/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 04:40:04 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Заметки]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=5619</guid>
		<description><![CDATA[Продолжаем изучать модули PowerShell, доступные только в RSAT для Widnows 7, хочу обратить Ваше внимание на модуль GroupPolicy. Напомню что в прошлый раз был модуль Active Directory. Модуль GroupPolicy доступен в следующих случаях: Windows Server 2008 R2 с установленной [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-6172" title="handcuffs" src="http://blog.wadmin.ru/wp-content/uploads/2012/02/handcuffs.jpg" alt="handcuffs" width="120" height="120" />Продолжаем изучать модули PowerShell, доступные только в RSAT для Widnows 7, хочу обратить Ваше внимание на модуль GroupPolicy.</p>
<p>Напомню что в прошлый раз был <a title="Модуль Active Directory для PowerShell" href="http://blog.wadmin.ru/2011/12/powershell-active-directory-module/">модуль Active Directory</a>.</p>
<p>Модуль <strong>GroupPolicy</strong> доступен в следующих случаях:</p>
<ul>
<li>Windows Server 2008 R2 с установленной ролью контроллера домена.</li>
<li>Рядовой сервер Windows Server 2008 R2 с установленной консолью GPMC.</li>
<li>Windows 7 с установленным пакетом Remote Server Administration Tools (RSAT).</li>
</ul>
<p>Казалось бы, нет ничего странного, модуль как модуль. Можно посмотреть какие в нем есть командлеты</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="kw1">Get-Command</span> <span class="sy0">-</span>Module GroupPolicy</div>
</div>
<p>или более правильная, по мнению курса Advanced Group Policy Troubleshooting, методика</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="kw1">Get-Command</span> <span class="sy0">*</span><span class="kw2">GP</span><span class="sy0">*</span></div>
</div>
<p>можно даже вот так</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="kw1">Get-Command</span> <span class="sy0">-</span>Module grouppolicy <span class="sy0">|</span> <span class="kw1">get-help</span> <span class="sy0">|</span> <span class="kw1">Format-Table</span> name<span class="sy0">,</span> synopsis <span class="kw5">-AutoSize</span> <span class="kw5">-Wrap</span></div>
</div>
<p>Результат не изменится, помощь есть помощь&#8230;</p>
<p>Набор более чем стандартный, есть и Get и Set и Remove, все хорошо документировано, ничего сложного и нет.</p>
<p><em>Примечание: полный список команд приводить не буду так как он доступен по <a href="http://technet.microsoft.com/en-us/library/ee461027.aspx" rel="nofollow">ссылке</a> на TechNet</em></p>
<p>Командлеты используются для выполнения нижеперечисленных операций с доменными объектами групповой политики:</p>
<ul>
<li>Создание, удаление, резервное копирование и импорт.</li>
<li>Создание, связывание, обновление и удаление связей объектов групповой политики с контейнерами Active Directory.</li>
<li>Установка флагов наследования и разрешений в подразделениях и доменах Active Directory.</li>
<li>Настройка реестровых параметров политики: обновление, извлечение, удаление.</li>
<li>Создание и изменение Started GPO.</li>
</ul>
<p>Постараюсь не размазывать а привести только самое интересное.</p>
<p>Для использования командлетов сначала импортируем модуль <strong>GroupPolicy</strong>.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">import<span class="sy0">-</span>module GroupPolicy</div>
</div>
<p><em>Примечание: Пока что все что приводится запускает от имени бесправного доменного пользователя. Позже объясню для чего это нужно.</em></p>
<p>Попробуем запросить список доступных объектов групповых политик.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">Get<span class="sy0">-</span>GPO <span class="sy0">-</span>All</div>
</div>
<p>Предположим что вы знаете список имеющихся OU, но забыли название а лезть в оснастку ADUC вам жутко лень. Что делать?</p>
<p>Все просто, вводим команду</p>
<pre>dsquery ou</pre>
<p>или тоже самое, но на powershell</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="br0">&#40;</span><span class="br0">&#91;</span>ADSISearcher<span class="br0">&#93;</span><span class="st0">&quot;objectClass=OrganizationalUnit&quot;</span><span class="br0">&#41;</span>.findall<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">|</span> <span class="kw1">select-Object</span> <span class="kw5">-property</span> path</div>
</div>
<p>Получаем результат.</p>
<blockquote><p>&laquo;OU=Domain Controllers,DC=lab,DC=com&raquo;<br />
&laquo;OU=Members Servers,DC=lab,DC=com&raquo;<br />
&laquo;OU=Managed Computers,DC=lab,DC=com&raquo;<br />
&laquo;OU=TestOU,DC=lab,DC=com&raquo;</p></blockquote>
<p>Структура ясна, теперь запрашиваем список объектов групповых политик для dc=lab,dc=com</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">Get<span class="sy0">-</span>GPInheritance <span class="sy0">-</span>Target <span class="st0">&quot;dc=lab,dc=com&quot;</span> <span class="sy0">-</span>Domain lab.com <span class="sy0">-</span>Server DC1</div>
</div>
<p>Результат вполне ожидаемый.</p>
<blockquote><p>Name : lab.com<br />
ContainerType : Domain<br />
Path : dc=lab,dc=com<br />
GpoInheritanceBlocked : No<br />
GpoLinks : {Default Domain Policy}<br />
InheritedGpoLinks : {Default Domain Policy}</p></blockquote>
<p>Теперь изучим политики привязанные к OU &#8211; Managed Computers.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">Get<span class="sy0">-</span>GPInheritance <span class="sy0">-</span>Target <span class="st0">&quot;ou=Managed Computers,dc=lab,dc=com&quot;</span> <span class="sy0">-</span>Domain lab.com <span class="sy0">-</span>Server DC1</div>
</div>
<p>В результате мы видим что в этому OU есть линк на политику &laquo;Desktop &#8211; Baseline Policy&raquo;. Посмотрим что можно прочитать про найденную политику.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">Get<span class="sy0">-</span>GPO <span class="kw5">-Name</span> <span class="st0">&quot;Desktop &#8211; Baseline Policy&quot;</span></div>
</div>
<p>Результат не впечатляет <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre>DisplayName      : Desktop - Baseline Policy
DomainName       : lab.com
Owner            : LAB\Domain Admins
Id               : 3aa02562-cf15-41a0-f8fb-416a2a421b4f
GpoStatus        : AllSettingsEnabled
Description      :
CreationTime     : 2/26/2011 12:15:42 AM
ModificationTime : 2/26/2011 12:15:42 AM
UserVersion      : AD Version: 0, SysVol Version: 0
ComputerVersion  : AD Version: 0, SysVol Version: 0
WmiFilter        :</pre>
<p><em>Примечание: На практике User Version и Computer Version, если заданы хоть какие нибудь настройки, явно не равняются нулю <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </em></p>
<p>Предположим, у нас есть некий набор настроенных GPO. Выполним  сначала запрос полномочий</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">Get<span class="sy0">-</span>GPPermissions <span class="kw5">-Name</span> <span class="st0">&quot;Desktop &#8211; Baseline Policy&quot;</span> <span class="sy0">-</span>All</div>
</div>
<p>а после него создадим отчет по имеющимся настройкам</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">Get<span class="sy0">-</span>GPOReport <span class="kw5">-Name</span> <span class="st0">&quot;Desktop &#8211; Baseline Policy&quot;</span> <span class="sy0">-</span>ReportType html <span class="sy0">&gt;</span> d:\Scripts\gp<span class="sy0">-</span>report.html</div>
</div>
<p>Получилось? Естественно. Ведь в правах скорее всего установлено что все прошедшие проверку могут читать.</p>
<p>Что остается сделать?</p>
<p>Наверное, резервную копию? Проверим получится или нет.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">Backup<span class="sy0">-</span>GPO <span class="kw5">-Name</span> <span class="st0">&quot;Desktop &#8211; Baseline Policy&quot;</span> <span class="kw5">-Path</span> D:\Scripts\backup <span class="sy0">-</span>Comment <span class="st0">&quot;test backup&quot;</span></div>
</div>
<p>Прокатило&#8230;</p>
<p><em>Примечание: Помните про &laquo;бесправного пользователя&raquo;? В данный момент с его правами удалось сделать резервную копию GPO.</em></p>
<p>Попробуем выполнить резервную копию всех объектов которые можно прочитать.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">Backup<span class="sy0">-</span>GPO <span class="sy0">-</span>All <span class="kw5">-Path</span> D:\Scripts\Backup\all <span class="sy0">-</span>Comment <span class="st0">&quot;test backup &#8211; all GPO&quot;</span></div>
</div>
<p>Получилось для всех имеющихся политик?</p>
<h3>Итог</h3>
<p>Каков вывод?<br />
Модуль GroupPolicy будет полезен администратору, например для автоматизации создания резервных копий объектов GPO и для аудита назначенных полномочий. Как показывает практика, остальные операции, как правило, выполняются из удобного графического интерфейса.</p>
<p>Если немного подумать, можно на базе модуля GroupPolicy написать скрипт для мониторинга изменений объектов. Например можно фиксировать следующие изменения:</p>
<ul>
<li>Изменения прав на объекты.</li>
<li>Изменение версий. Атрибуты UserVersion и ComputerVersion.</li>
<li>Создание новых объектов.</li>
<li>&#8230;</li>
</ul>
<p>Второй вариант немного неожиданный т.к. он основан на стандартном заблуждении многих админов заключенных в том что назначения стандартных разрешений для объектов GPO вполне достаточно.</p>
<p>Проблема сводится к тому что в большинстве случаев почти все объекты GPO можно прочитать, ошибка может привести к следующим последствиям.</p>
<p>Предположите на мгновения что некто сделал резервную копию GPO в котором у вас задаются пароли для локальных администраторов или настройки для сервисов&#8230;</p>
<p>Представили?</p>
<p>Дальнейшая судьба этих GPO скорее всего будет следующей:</p>
<ul>
<li>Резервная копия будет восстановлена в тестовом окружении.</li>
<li>GPO назначено на OU.</li>
<li>После применения политики будут слиты хэши от пользователей которых вы настроили (например назначили пароль локальному администратору через Group Policy Preference) или получены <a title="Альтернатива SAPD.exe средствами PowerShell" href="http://blog.wadmin.ru/2011/12/reading-lsa-service-account-secrets-using-powershell/">пароли учетных записей</a> от которых стартуют сервисы (частенько это могут оказаться учетки с правами доменного администратора или учетные записи пользователей имеющих очень большие права <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).</li>
</ul>
<p>Вариантов масса. Могу предположить сценарий похищения политик которые отвечают за настройки серверов с целью их анализа и пр.<br />
Конечно, если у вас все в порядке с правами доступа к объектам, то вам вышеназванные жутики вам не страшны, но если у вас все могут читать то стоит задуматься&#8230;</p>
<p>PS Это не методика взлома Групповых политик, это повод задуматься над тем что у вас есть сейчас.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2012/02/powershell-grouppolicy-module/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Сбор запланированных заданий средствами PowerShell</title>
		<link>http://blog.wadmin.ru/2012/01/get-sched-task/</link>
		<comments>http://blog.wadmin.ru/2012/01/get-sched-task/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 07:11:13 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Инструменты]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=5821</guid>
		<description><![CDATA[Запланированные задания. Казалось, что может быть проще..? Есть утилита schtasks.exe, она умеет собирать, создавать и удалять задания. Пишем schtasks.exe /? и далее по обстоятельствам, вернее по необходимости. Однако не все так просто как кажется. При [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-5892" title="запланированные задания" src="http://blog.wadmin.ru/wp-content/uploads/2012/01/yo-e1326956667661.jpeg" alt="запланированные задания" width="120" height="115" />Запланированные задания. Казалось, что может быть проще..?</p>
<p>Есть утилита <strong>schtasks.exe</strong>, она умеет собирать, создавать и удалять задания. Пишем</p>
<pre>schtasks.exe /?</pre>
<p>и далее по обстоятельствам, вернее по необходимости.</p>
<p>Однако не все так просто как кажется. При наличии десятка серверов все кажется простым и понятным, но при наличии 500 и более серверов задача слегка усложняется. Вполне возможно что на рабочих станциях включен планировщик и вам необходимо собрать данные по запланированному заданию которое вы назначили через GPP, как пример можно привести <a title="Управление FEP 2010 без SCCM" href="http://blog.wadmin.ru/2012/01/manage-fep-2010-without-sccm/">задачу по развертыванию</a> FEP 2010.</p>
<p><em>Примечание: Вопрос управления заданиями уже <a href="http://blog.wadmin.ru/2011/01/managing-scheduled-tasks/">обсуждался</a>, но это не мешает нам к нему вернуться.</em></p>
<p>Простой метод сбора информации о запланированных заданий приведен ниже. Скрипт формирует CSV файл который потом замечательно можно проанализировать в Excel.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="co1"># добавляем снапин от Quest</span><br />
<span class="kw1">Add-PSSnapin</span> Quest.ActiveRoles.ADManagement</p>
<p><span class="co1"># задаем нужный OU</span><br />
<span class="re0">$OU</span> <span class="sy0">=</span> <span class="st0">&#8216;Domain/Members Servers&#8217;</span></p>
<p><span class="co1"># указываем имя файла отчета</span><br />
<span class="re0">$reportFile</span> <span class="sy0">=</span> <span class="st0">&quot;report.txt&quot;</span></p>
<p><span class="re0">$servers</span> <span class="sy0">=</span> Get<span class="sy0">-</span>QADComputer <span class="sy0">-</span>SearchRoot <span class="re0">$OU</span> <span class="sy0">-</span>SearchScope Subtree</p>
<p><span class="kw3">foreach</span> <span class="br0">&#40;</span><span class="re0">$server</span> <span class="kw3">in</span> <span class="re0">$servers</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="kw1">Write-Host</span> <span class="re0">$server</span>.dnshostname<br />
<span class="re0">$tasks</span> <span class="sy0">=</span> schtasks.exe <span class="sy0">/</span>Query <span class="sy0">/</span>FO CSV <span class="sy0">/</span>v <span class="sy0">/</span>s <span class="re0">$server</span>.dnshostname<br />
<span class="re0">$tasks</span> <span class="sy0">|</span> <span class="kw2">ft</span> HostName<span class="sy0">,</span>TaskName<span class="sy0">,</span><span class="st0">&quot;Last Run Time&quot;</span> <span class="sy0">|</span> <span class="kw1">Out<span class="kw4">-File</span></span> <span class="kw5">-NoClobber</span> <span class="kw5">-Append</span> <span class="re0">$reportFile</span><br />
<span class="co1"># если нет задачи выводить информацию в файл, а сразу получать результат на экран то можно </span><br />
<span class="co1"># сделать следующим образом.</span><br />
<span class="co1"># $tasks | ConvertFrom-Csv | ft HostName,TaskName,&quot;Last Run Time&quot;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>PS Как мне правильно заметили эта публикация является модификацией более старой <a href="http://blog.wadmin.ru/2010/04/audit-scheduled-tasks/">статьи</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2012/01/get-sched-task/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>PowerShell &#8211; мониторинг состава групп</title>
		<link>http://blog.wadmin.ru/2012/01/powershell-group-member-monitoring/</link>
		<comments>http://blog.wadmin.ru/2012/01/powershell-group-member-monitoring/#comments</comments>
		<pubDate>Tue, 17 Jan 2012 07:12:02 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Инструменты]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=5860</guid>
		<description><![CDATA[Хороший знакомый попросим меня &#171;по быстрому&#187; набросать скрипт для мониторинга изменения участников групп в Active Directory. Получилось кривовато, но вполне работоспособно. Логика работы скрипта проста: Создаем текстовые файлы по именам групп при первом запуске. При следующих запусках [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-3915" title="powershell" src="http://blog.wadmin.ru/wp-content/uploads/2011/07/powershell-e1323611870272.png" alt="powershell" width="120" height="120" />Хороший знакомый попросим меня &laquo;по быстрому&raquo; набросать скрипт для мониторинга изменения участников групп в Active Directory.</p>
<p>Получилось кривовато, но вполне работоспособно. Логика работы скрипта проста:</p>
<ul>
<li>Создаем текстовые файлы по именам групп при первом запуске.</li>
<li>При следующих запусках сравниваем текущее состояние с тем что есть в старых файлах.</li>
<li>При необходимости пишем в файл отчета.</li>
<li>Удаляем старый файл, создаем новый и записываем в него состав группы.</li>
</ul>
<p>На всякий случай текст скрипта в текстовом формате &#8211; <a href="http://blog.wadmin.ru/downloads/adGroupCheck.ps1.txt">скачать</a>.</p>
<p><em>Примечание: По мере &laquo;шлифовки&raquo; будут вносится правки.</em></p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="co1"># добавляем снапин от Quest</span><br />
<span class="kw1">Add-PSSnapin</span> Quest.ActiveRoles.ADManagement</p>
<p><span class="co1"># задаем формат даты</span><br />
<span class="re0">$currentDate</span> <span class="sy0">=</span> <span class="kw1">Get-Date</span> <span class="kw5">-format</span> M.d.yyyy</p>
<p><span class="co1"># указываем нужные пути и файл отчета</span><br />
<span class="re0">$reportFolder</span> <span class="sy0">=</span> <span class="st0">&quot;D:\Scripts\Powershell\GroupCheck\&quot;</span><br />
<span class="re0">$report</span> <span class="sy0">=</span> <span class="st0">&quot;D:\Scripts\Powershell\$($currentDate)_report.txt&quot;</span></p>
<p><span class="co1"># собираем данные о группах</span><br />
<span class="re0">$groups</span> <span class="sy0">=</span> Get<span class="sy0">-</span>QADGroup <span class="sy0">-</span>SizeLimit 0<br />
<span class="re0">$PreviousDay</span> <span class="sy0">=</span> <span class="sy0">@</span><span class="br0">&#123;</span><span class="br0">&#125;</span></p>
<p><span class="co1"># функция сравнения </span><br />
<span class="kw3">function</span> CompareResults <span class="br0">&#40;</span><span class="re0">$query</span><span class="sy0">,</span> <span class="re0">$group</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">foreach</span> <span class="br0">&#40;</span><span class="re0">$result</span> <span class="kw3">in</span> <span class="re0">$query</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># пользователь добавлен в группу</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">if</span> <span class="br0">&#40;</span><span class="re0">$result</span>.SideIndicator <span class="kw4">-eq</span> <span class="st0">&quot;=&gt;&quot;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">Write-Output</span> <span class="st0">&quot;User added &#8211; $($result.InputObject.NTAccountName)&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Group $($group). add user &#8211; $($result.InputObject.NTAccountName)&quot;</span> <span class="sy0">|</span> <span class="kw1">Out<span class="kw4">-File</span></span> <span class="kw5">-Append</span> <span class="re0">$report</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># пользователь удален из группы</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">if</span> <span class="br0">&#40;</span><span class="re0">$result</span>.SideIndicator <span class="kw4">-eq</span> <span class="st0">&quot;&lt;=&quot;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">Write-Output</span> <span class="st0">&quot;User removed &#8211; $($result.InputObject)&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;Group $($group). remove user &#8211; $($result.InputObject)&quot;</span> <span class="sy0">|</span> <span class="kw1">Out<span class="kw4">-File</span></span> <span class="kw5">-Append</span> <span class="re0">$report</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw3">foreach</span> <span class="br0">&#40;</span><span class="re0">$group</span> <span class="kw3">in</span> <span class="re0">$Groups</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$fileName</span> <span class="sy0">=</span> <span class="re0">$reportFolder</span> <span class="sy0">+</span> <span class="re0">$group</span> <span class="sy0">+</span> <span class="st0">&quot;.txt&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="br0">&#40;</span><span class="kw1">Test-Path</span> <span class="re0">$fileName</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">New-Item</span> <span class="re0">$fileName</span> <span class="kw5">-ItemType</span> file <span class="kw5">-Force</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$PreviousDay</span><span class="br0">&#91;</span><span class="re0">$group</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw1">Get-Content</span> <span class="re0">$fileName</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$MemberList</span> <span class="sy0">=</span> Get<span class="sy0">-</span>QADGroupMember <span class="re0">$group</span> <span class="sy0">-</span>SizeLimit 0<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$PreviousList</span> <span class="sy0">=</span> <span class="kw1">Get-Content</span> <span class="re0">$fileName</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp;<span class="kw3">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re0">$MemberList</span> <span class="kw4">-ne</span> <span class="re0">$null</span><span class="br0">&#41;</span> <span class="kw4">-and</span> <span class="br0">&#40;</span><span class="re0">$PreviousList</span> <span class="kw4">-eq</span> <span class="re0">$null</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">foreach</span> <span class="br0">&#40;</span><span class="re0">$user</span> <span class="kw3">in</span> <span class="re0">$MemberList</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">Write-Output</span> <span class="st0">&quot;$($group): Add user – $($user.NTAccountName)&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw3">elseif</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re0">$MemberList</span> <span class="kw4">-eq</span> <span class="re0">$null</span><span class="br0">&#41;</span> <span class="kw4">-and</span> <span class="br0">&#40;</span><span class="re0">$PreviousList</span> <span class="kw4">-ne</span> <span class="re0">$null</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">foreach</span> <span class="br0">&#40;</span><span class="re0">$user</span> <span class="kw3">in</span> <span class="re0">$PreviousList</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">Write-Output</span> <span class="st0">&quot;$($group): Remove user – $user&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw3">elseif</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re0">$MemberList</span> <span class="kw4">-ne</span> <span class="re0">$null</span><span class="br0">&#41;</span> <span class="kw4">-and</span> <span class="br0">&#40;</span><span class="re0">$PreviousList</span> <span class="kw4">-ne</span> <span class="re0">$null</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># анализ группы</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">Write-Output</span> <span class="st0">&quot;Check group – $($group)&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$DiffResult</span> <span class="sy0">=</span> <span class="kw2">diff</span> <span class="kw5">-ReferenceObject</span> <span class="re0">$PreviousList</span> <span class="kw5">-DifferenceObject</span> <span class="re0">$MemberList</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CompareResults <span class="re0">$DiffResult</span> <span class="re0">$group</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw3">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># пустая группа</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">Write-Output</span> <span class="st0">&quot;Group $group – has no members&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$MemberList</span> <span class="sy0">|</span> <span class="kw1">Select-Object</span> <span class="kw5">-Expand</span> NTAccountName <span class="sy0">|</span> <span class="kw1">Out<span class="kw4">-File</span></span> <span class="re0">$fileName</span><br />
<span class="br0">&#125;</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2012/01/powershell-group-member-monitoring/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Читаем RSS средствами PowerShell</title>
		<link>http://blog.wadmin.ru/2011/12/read-rss-via-powershell/</link>
		<comments>http://blog.wadmin.ru/2011/12/read-rss-via-powershell/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 09:56:37 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Заметки]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=5526</guid>
		<description><![CDATA[В процессе предпраздничного разгребания накопленных черновиков нашелся скрипт для получения RSS лент средствами PowerShell. Вещь простая, совершенно бесполезная (я для нее практического применения не нашел), но упомянуть ее стоит. Хотя, вполне можно придумать сценарий когда [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-3915" title="powershell" src="http://blog.wadmin.ru/wp-content/uploads/2011/07/powershell-e1323611870272.png" alt="powershell" width="120" height="120" />В процессе предпраздничного разгребания накопленных черновиков нашелся скрипт для получения <strong>RSS</strong> лент средствами <strong>PowerShell</strong>.</p>
<p>Вещь простая, совершенно бесполезная (я для нее практического применения не нашел), но упомянуть ее стоит.</p>
<p>Хотя, вполне можно придумать сценарий когда у вас на рабочей станции  нет никаких ридеров, но есть доступ в интернет и злой дядька сисадмин не дает запускать ничего кроме IE который ходит только на один узел <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Придумать можно все что угодно&#8230;</p>
<p>Скрипт простой, вот он:</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="co1"># задаем адрес канала</span><br />
<span class="re0">$feed</span><span class="sy0">=</span><span class="st0">&quot;http://feeds.feedburner.com/wmemories&quot;</span><br />
<span class="co1"># создаем объект System.Net.WebClient</span><br />
<span class="re0">$client</span> <span class="sy0">=</span> <span class="kw1">New-Object</span> System.Net.WebClient<br />
<span class="co1"># задаем кодировку. Без нее будут выводится крякозябры</span><br />
<span class="re0">$client</span>.Encoding <span class="sy0">=</span> <span class="br0">&#91;</span>System.Text.Encoding<span class="br0">&#93;</span>::UTF8</p>
<p><span class="re0">$rss</span> <span class="sy0">=</span> <span class="br0">&#91;</span><span class="re3">xml</span><span class="br0">&#93;</span><span class="re0">$client</span>.DownloadString<span class="br0">&#40;</span><span class="re0">$feed</span><span class="br0">&#41;</span><br />
<span class="co1"># получаем все что есть</span><br />
<span class="re0">$rss</span>.rss.channel.item <span class="sy0">|</span> <span class="kw1">format-list</span><br />
<span class="co1"># или компактно выводим результаты в форме таблички</span><br />
<span class="re0">$rss</span>.rss.channel.item <span class="sy0">|</span> <span class="kw1">format-table</span> title<span class="sy0">,</span>pubDate<span class="sy0">,</span> link</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2011/12/read-rss-via-powershell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Получаем Uptime в Windows.</title>
		<link>http://blog.wadmin.ru/2011/12/windows-uptime/</link>
		<comments>http://blog.wadmin.ru/2011/12/windows-uptime/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 08:55:34 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Инструменты]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=5529</guid>
		<description><![CDATA[Когда то давно вопрос получение uptime от серверов уже поднимался, но в предновогодние дни стоит затронуть его еще раз&#8230; Назову причину &#8211; коллега забыл про сервер разработки и его аптайм до вчерашнего дня составил 832 [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-5547" title="uptime" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/uptime-e1325062702824.jpg" alt="uptime" width="120" height="110" />Когда то давно вопрос <a href="http://blog.wadmin.ru/2009/10/servers-uptime/">получение uptime</a> от серверов уже поднимался, но в предновогодние дни стоит затронуть его еще раз&#8230;</p>
<p>Назову причину &#8211; коллега забыл про сервер разработки и его аптайм до вчерашнего дня составил 832 дня !</p>
<p><em>Молиться надо на таких разработчиков раз они не только не уронили, но и не доставали более двух лет <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </em></p>
<p>В любом случае на цифирьки посмотреть не мешает, при большом аптайме, как минимум не установлены критические обновления. И закончится это может в любой момент и вероятность того что закончится оно &laquo;плохо&raquo; или &laquo;могло быть и лучше если бы почесались&raquo;&#8230;</p>
<p>Да простят меня &laquo;линуксоиды&raquo;, мерится аптаймами не будем <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  просто посмотрим как можно получить нужную цифру и на методики получения информации о том сколько у нас отработала система.</p>
<p><em>Примечание: Коллеги линукс-админы, это не камень в ваш огород, я знаю много отличных специалистов, но в ваших рядах затесались (в семье не без урода) те кто свято верит в то что сервер с ядром 2.2 и аптаймом в 5 лет совершенно безопасен и стабилен (при этом сервер светится как новогодняя елка во внешний мир). Я не поддерживаю такого и чаще всего просто не понимаю. Дискуссии про то что линукс мега надежен и супер стабилен и про то что виндофс  бяка поддерживать не буду. Надеюсь на понимание.</em></p>
<p>Специально для тех кто забывает про серверы&#8230;</p>
<h3>Используем Диспетчер Задач</h3>
<p>В Windows Vista и Windows Server 2008, в диспетчере задач есть возможность посмотреть аптайм.</p>
<ol>
<li>На таскбаре жмем мышом и выбираем Task Manager. Можно использовать комбинацию CTRL+SHIFT+ESC. Тут уж кто как привык.</li>
<li>Выбираем вкладку Performance.</li>
<li>В свойствах System видим нужное значение.</li>
</ol>
<p><img class="aligncenter size-full wp-image-5534" title="taskmgr" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/taskmgr.png" alt="taskmgr" width="400" height="409" /></p>
<p><em>Примечание: К сожалению данная методика не доступна в Windows 2003. </em></p>
<h3>Используем утилиту systeminfo</h3>
<p>Меня часто удивляет тот факт что про утилиту systeminfo почему то все забывают. Тем не менее она дает не только массу информации, но и нужное нам значение последней загрузки системы.</p>
<p>Открываем командную строку и вводим:</p>
<pre>systeminfo | find "System Boot Time:"</pre>
<p><img class="aligncenter size-full wp-image-5535" title="systeminfo" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/systeminfo.png" alt="systeminfo" width="481" height="205" /></p>
<p>&nbsp;</p>
<h3>Утилита Uptime</h3>
<p>Для удобства Microsoft сделал довольно полезный инструмент который можно получить по ссылке:</p>
<p><a href="http://support.microsoft.com/kb/232243" rel="nofollow" target="_blank">http://support.microsoft.com/kb/232243</a></p>
<p>Для использования необходимо:</p>
<ul>
<li>Загрузить утилиту.</li>
<li>Запихнуть ее в папку которая включена в переменную %PATH%</li>
<li>Для получения справки используйте ключ /?</li>
<li>Если справка не требуется то вводите.
<pre>uptime.exe</pre>
</li>
</ul>
<p><img class="aligncenter size-full wp-image-5536" title="uptime" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/uptime.png" alt="uptime" width="450" height="73" /></p>
<h3>Используем утилиту NET STATISTICS</h3>
<p>В выводе команды:</p>
<pre>net statistics workstation</pre>
<p>Среди предоставленной информации есть время последней загрузки системы</p>
<p><img class="aligncenter size-full wp-image-5537" title="statistics" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/statistics.png" alt="statistics" width="450" height="173" /></p>
<h3>Используем Event Viewer</h3>
<p>Метод заключен в поиске сообщения с кодом 6005 (запуск сервиса EventLog) от источника EventLog и события с кодом 6006 (остановка сервиса EventLog)</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="kw1">Get-EventLog</span> <span class="kw5">-LogName</span> system <span class="sy0">|</span> <span class="kw1">Where-Object</span> <span class="br0">&#123;</span><a href="about:blank"><span class="kw6">$_</span></a>.EventID <span class="kw4">-eq</span> 6005 <span class="kw4">-or</span> <a href="about:blank"><span class="kw6">$_</span></a>.EventID <span class="kw4">-eq</span> 6006<span class="br0">&#125;</span> <span class="sy0">|</span> <span class="kw2">Select</span> TimeGenerated<span class="sy0">,</span> EventID</div>
</div>
<p>Естественно эту же информацию легко получить с удаленного хоста введя команду:</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="kw1">Get-EventLog</span> <span class="kw5">-LogName</span> system <span class="sy0">-</span>Computer HOST_NAME <span class="sy0">-</span>Credentil <span class="br0">&#40;</span><span class="kw1">Get-Credential</span><span class="br0">&#41;</span><span class="sy0">|</span> <span class="kw1">Where-Object</span> <span class="br0">&#123;</span><a href="about:blank"><span class="kw6">$_</span></a>.EventID <span class="kw4">-eq</span> 6005 <span class="kw4">-or</span> <a href="about:blank"><span class="kw6">$_</span></a>.EventID <span class="kw4">-eq</span> 6006<span class="br0">&#125;</span> <span class="sy0">|</span> <span class="kw2">Select</span> TimeGenerated<span class="sy0">,</span> EventID</div>
</div>
<p>Более просто этот метод реализуется просмотром журнала System и поиска событий с кодами 6005 и 6006.<br />
<img class="aligncenter size-full wp-image-5538" title="system-uptime" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/system-uptime-e1325054128372.png" alt="system-uptime" width="600" height="417" /></p>
<h3>Используем WMI</h3>
<p>У WMI класса <strong>Win32_PerfFormattedData_PerfOS_System</strong> есть счетчик SystemUptime, который можно использовать для получения необходимого значения.</p>
<div class="codesnip-container" >
<div class="vb codesnip" style="font-family:monospace;"># указываем текущий компьютер<br />
strComputer = <span class="st0">&quot;.&quot;</span><br />
<span class="kw1">Set</span> objWMIService = GetObject(<span class="st0">&quot;winmgmts:\\&quot;</span> &amp; strComputer &amp; <span class="st0">&quot;\root\cimv2&quot;</span>)<br />
<span class="kw1">Set</span> colOperatingSystems = objWMIService.ExecQuery (<span class="st0">&quot;Select * From Win32_PerfFormattedData_PerfOS_System&quot;</span>)</p>
<p><span class="kw1">For</span> <span class="kw1">Each</span> objOS <span class="kw1">in</span> colOperatingSystems<br />
# для получения минут делим SystemUpTime на 60<br />
intSystemUptime = Int(objOS.SystemUpTime / 60)<br />
strMessage = <span class="st0">&quot;System uptime is &quot;</span> &amp; intSystemUptime &amp; <span class="st0">&quot; minutes&quot;</span><br />
msgBox strMessage, 0, <span class="st0">&quot;System Uptime&quot;</span><br />
<span class="kw1">Next</span></div>
</div>
<p>Можно использовать LastBootUpTime из класса Win32_OperatingSystem, но об этом в следующем методе.</p>
<h3>Используем PowerShell</h3>
<p>В данном методе используется WMI класс <strong>Win32_OperatingSystem</strong> и разница по времени между LocalDateTime и LastBootUpTime.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="re0">$wmi</span> <span class="sy0">=</span> <span class="kw1">Get-WmiObject</span> <span class="kw5">-Class</span> Win32_OperatingSystem<br />
<span class="re0">$wmi</span>.ConvertToDateTime<span class="br0">&#40;</span><span class="re0">$wmi</span>.LocalDateTime<span class="br0">&#41;</span> – <span class="re0">$wmi</span>.ConvertToDateTime<span class="br0">&#40;</span><span class="re0">$wmi</span>.LastBootUpTime<span class="br0">&#41;</span></div>
</div>
<p>Получаемся не совсем аккуратная &laquo;простыня&raquo;</p>
<pre>Days              : 12
Hours             : 22
Minutes           : 18
Seconds           : 29
Milliseconds      : 912
Ticks             : 11171099124010
TotalDays         : 12,9295128750116
TotalHours        : 310,308309000278
TotalMinutes      : 18618,4985400167
TotalSeconds      : 1117109,912401
TotalMilliseconds : 1117109912,401</pre>
<p>Более компактного вывода можно добиться командой которая дает немножко нестандартный, но все же вывод.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="br0">&#91;</span>math<span class="br0">&#93;</span>::round<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw1">Get-Date</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="br0">&#40;</span><span class="re0">$q</span><span class="sy0">=</span><span class="kw2">gwmi</span> Win32_OperatingSystem<span class="br0">&#41;</span>.ConvertToDateTime<span class="br0">&#40;</span><span class="re0">$q</span>.lastbootuptime<span class="br0">&#41;</span><span class="br0">&#41;</span>.TotalDays<span class="sy0">,</span> <span class="nu0">2</span><span class="br0">&#41;</span></div>
</div>
<p>Более наглядный вариант умеющий выводить в файл результаты:</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><a href="about:blank"><span class="kw6">$ErrorActionPreference</span></a> <span class="sy0">=</span> <span class="st0">&quot;SilentlyContinue&quot;</span><br />
<span class="re0">$reportFile</span> <span class="sy0">=</span> <span class="st0">&quot;D:\Scripts\Output\LastReboot.htm&quot;</span><br />
<span class="re0">$reportFolder</span> <span class="sy0">=</span> <span class="st0">&quot;D:\Scripts\Output&quot;</span><br />
<span class="kw1">Remove-Item</span> <span class="re0">$reportFolder</span> <span class="kw5">-Recurse</span></p>
<p><span class="re0">$InputFile</span> <span class="sy0">=</span> <span class="kw1">Get-Content</span> Servers.txt<br />
<span class="re0">$LastReboot</span> <span class="sy0">=</span> <span class="sy0">@</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw3">foreach</span> <span class="br0">&#40;</span><span class="re0">$computer</span> <span class="kw3">in</span> <span class="re0">$InputFile</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$q</span> <span class="sy0">=</span> <span class="st0">&quot;&quot;</span> <span class="sy0">|</span> <span class="kw1">Select-Object</span> <span class="st0">&#8216;Machine Name&#8217;</span><span class="sy0">,</span><span class="st0">&#8216;Last Reboot TimeStamp&#8217;</span><span class="sy0">,</span><span class="st0">&#8216;Reboot Initiator&#8217;</span><span class="sy0">,</span><span class="st0">&#8216;Reboot Reason Code&#8217;</span><br />
<span class="re0">$q</span>.<span class="st0">&#8216;Machine Name&#8217;</span> <span class="sy0">=</span> <span class="re0">$computer</span><br />
<span class="re0">$q</span>.<span class="st0">&#8216;Last Reboot TimeStamp&#8217;</span> <span class="sy0">=</span> <span class="br0">&#91;</span>Management.ManagementDateTimeConverter<span class="br0">&#93;</span>::ToDateTime<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw1">Get-WmiObject</span> <span class="kw5">-class</span> Win32_OperatingSystem <span class="kw5">-computername</span> <span class="re0">$computer</span> <span class="kw5">-namespace</span> <span class="st0">&quot;root\CIMV2&quot;</span><span class="br0">&#41;</span>.LastBootUpTime<span class="br0">&#41;</span><br />
<span class="re0">$LastReboot</span> <span class="sy0">+=</span> <span class="re0">$q</span><br />
<span class="br0">&#125;</span><br />
<span class="kw1">New-Item</span> <span class="re0">$reportFolder</span> <span class="kw5">-ItemType</span> directory</p>
<p><span class="re0">$LastReboot</span> <span class="sy0">|</span> <span class="kw1">Sort-Object</span> <span class="st0">&#8216;Last Reboot TimeStamp&#8217;</span> <span class="kw5">-Descending</span> <span class="sy0">|</span> <span class="kw1">ConvertTo-Html</span> <span class="sy0">|</span> <span class="kw1">Out<span class="kw4">-File</span></span> <span class="re0">$reportFile</span><br />
<span class="kw1">Invoke-Expression</span> $reportFile</div>
</div>
<p>PS несмотря на обилие методик я все же предпочитаю &laquo;дедовский метод&raquo; &#8211; утилиту uptime.exe.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2011/12/windows-uptime/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Модуль Active Directory для PowerShell</title>
		<link>http://blog.wadmin.ru/2011/12/powershell-active-directory-module/</link>
		<comments>http://blog.wadmin.ru/2011/12/powershell-active-directory-module/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 09:43:31 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Заметки]]></category>
		<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=4441</guid>
		<description><![CDATA[На днях спорил с одним из коллег по методикам управления Active Directory средствами PowerShell-а. Коллега доказывал что нет ничего лучше и удобнее чем PowerGUI, но он либо забыл либо не учел что есть еще Active [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-3915" title="powershell" src="http://blog.wadmin.ru/wp-content/uploads/2011/07/powershell-e1323611870272.png" alt="powershell" width="120" height="120" />На днях спорил с одним из коллег по методикам управления Active Directory средствами PowerShell-а.</p>
<p>Коллега доказывал что нет ничего лучше и удобнее чем <strong>PowerGUI</strong>, но он либо забыл либо не учел что есть еще <strong>Active Directory Module for Windows PowerShell</strong> и не учел то что PowerGUI хоть и удобен, но все же является сторонним средством которое надо хотя бы изредка обновлять.</p>
<p>Собственно, ниже речь пойдет о том как установить и о методиках использования модуля Active Directory для PowerShell.</p>
<h3>Устанавливаем Active Directory Module для Windows PowerShell</h3>
<p>С выходом PowerShell 2.0 мы получили замечательный модуль для администрирования Active Directory. Модуль Active Directory для Windows PowerShell работает на Windows Server 2008 R2 и на Windows 7, для его работы необходим веб-сервис который должен быть размещен на одном из контроллеров домена.</p>
<h3>Подготовка контроллера домена</h3>
<p>Для работы нам понадобится установка Active Directory Web Services (ADWS) на контроллере с Windows Server 2008 R2 AD DS. В случае если у вас нет контроллера на Windows Server 2008 R2, можно установить Active Directory Management Gateway Service на имеющиеся системы список которых есть чуть ниже.</p>
<p>Загрузить Active Directory Management Gateway Service можно <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=008940c6-0296-4597-be3e-1d24c1cf0dda&amp;displayLang=en" target="_blank">здесь</a>.</p>
<p>Установку производится на следующие ОС:</p>
<ul>
<li>Windows Server 2003 R2 with Service Pack 2</li>
<li>Windows Server 2003 SP2</li>
<li>Windows Server 2008</li>
<li>Windows Server 2008 SP2</li>
</ul>
<p>После установки появится новый сервис:</p>
<p><img class="aligncenter size-full wp-image-5316" title="adws-service" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/adws-service.jpg" alt="adws-service" width="600" height="166" /></p>
<p>Теперь можно устанавливать модуль Active Directory для Windows PowerShell. Он доступен на всех версиях Windows Server 2008 R2 (кроме Web Edition) и на Windows 7.</p>
<h3>Установка Active Directory Module для Windows PowerShell на 2008 R2</h3>
<p>Первый вариант установки слегка устарел, но он вполне работоспособен. Запускаем cmd.exe, вводим:</p>
<pre>Servermanagercmd -install RSAT-AD-PowerShell
Servermanagercmd -install RSAT-AD-AdminCenter</pre>
<p>Второй вариант установки доступен через добавление фичи RSAT-AD-PowerShell и для полного комплекта еще и RSAT-AD-AdminCenter (для кучи), через выполнение следующих команд:</p>
<p><span class="Apple-style-span" style="font-family: Consolas, Monaco, monospace; font-size: 12px; line-height: 18px; white-space: pre;">Import-Module ServerManager</span></p>
<pre>Add-WindowsFeature RSAT-AD-PowerShell
Add-WindowsFeature RSAT-AD-AdminCenter</pre>
<p><em>Примечание: Перечисленные ниже команды относятся только к рядовому серверу Windows Server 2008 R2членом, на контроллере RSAT-AD-PowerShell функция будет установлена во время выполнения DCPromo.</em></p>
<h3>Установка Remote Server Administration Tools (RSAT) для Windows 7</h3>
<p>Чтобы установить Модуль Active Directory для Windows PowerShell, Вы должны загрузить <strong>RSAT</strong> (Remote Server Administration Tools)  для Windows 7 <a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=7887">здесь</a>.</p>
<p>После завершения установки открываем &laquo;Control Panel&raquo; &#8211; &laquo;Programs and &raquo; &#8211; &laquo;Turn Windows features on or off&raquo; и выбираем Модуль &laquo;Active Directory for Windows PowerShell&raquo;:</p>
<p><a href="http://blog.wadmin.ru/wp-content/uploads/2011/12/add-win-features.jpg"><img class="aligncenter size-full wp-image-5320" title="add-win-features" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/add-win-features.jpg" alt="add-win-features" width="400" height="339" /></a></p>
<p>По умолчанию с модулем &laquo;Active Directory for PowerShell&raquo; устанавливаются следующие компоненты.</p>
<ul>
<li>Windows PowerShell</li>
<li>Платформа Microsoft .NET Framework 3.5.1</li>
</ul>
<p>После запуска ADWS установленных хотя бы на один контроллер можно запускать установленный модуль &raquo;Active Directory for PowerShell&raquo; одним из способов:</p>
<p><strong>Метод №1</strong></p>
<p>Открываем &laquo;Control Panel&raquo; &#8211; &laquo;Administrative Tools&raquo; &#8211; &laquo;Active Directory Module for Windows Powershell&raquo;</p>
<p><img class="aligncenter size-full wp-image-5340" title="Active Directory for PowerShell" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/pic-15.png" alt="Active Directory for PowerShell" width="602" height="280" /></p>
<p>Нажимаем правой кнопкой мыши и выбираем &raquo;Run as administrator&raquo;.</p>
<p><strong>Метод №2</strong></p>
<p>Я предпочитаю второй вариант т.е. импорт AD PowerShell модуля прямо из сессии PowerShell. Для этого выполняем следующую команду:</p>
<pre>Import-Module ActiveDirectory</pre>
<h3>Использование</h3>
<p>Импорт модуля мы произвели ранее, но на всякий случай убеждаемся что он у нас есть:</p>
<pre>get-module -ListAvailable

ModuleType Name                      ExportedCommands
---------- ----                      ----------------
Manifest   <strong>ActiveDirectory</strong>           {}
Manifest   AppLocker                 {}
Manifest   BitsTransfer              {}
Manifest   GroupPolicy               {}
...</pre>
<p>Нужный модуль есть в списке, импортируем его:</p>
<pre>Import-Module ActiveDirectory</pre>
<p>Изучаем домен с помощью командлета Get-ADDomain. Полный вывод давать не буду, тут и ниже буду приводить только чать.</p>
<pre>Get-ADDomain

ChildDomains                       : {}
ComputersContainer                 : OU=Computers,OU=Preparation,OU=test-lab,DC=lab,DC=local
DistinguishedName                  : DC=lab,DC=local
DNSRoot                            : LAB.LOCAL
DomainControllersContainer         : OU=Domain Controllers,DC=LAB,DC=LOCAL
DomainMode                         : Windows2003Domain
InfrastructureMaster               : DC01.LAB.LOCAL
Name                               : LAB
NetBIOSName                        : RETAIL
ParentDomain                       : {}
PDCEmulator                        : DC01.LAB.LOCAL
ReplicaDirectoryServers            : {dc02.LAB.LOCAL}
RIDMaster                          : DC01.LAB.LOCAL
UsersContainer                     : OU=Users,OU=Preparation,OU=test-lab,DC=lab,DC=local</pre>
<p>Информативно, не правда ли?<br />
Теперь мы знаем имя домена, имена контроллеров</p>
<pre>
(Get-ADDomain).ReplicaDirectoryServers
</pre>
<p>держателей FSMO ролей, режим и пр.</p>
<p>Теперь вводим:</p>
<pre>Get-ADDomainController
Domain                     : LAB.LOCAL
Enabled                    : True
HostName                   : DC01.LAB.LOCAL
IPv4Address                : 192.168.0.1
IPv6Address                :
IsGlobalCatalog            : True
IsReadOnly                 : False
LdapPort                   : 389
Name                       : DC01
OperatingSystem            : Windows Server 2008 R2 Standard
OperatingSystemVersion     : 6.1 (7600)
OperationMasterRoles       : {PDCEmulator, RIDMaster}
Site                       : LABSite</pre>
<p>Вывод &laquo;порезан&raquo;, но из него видно что операционная система у нас Windows Server 2008 R2 Standard, что этот контроллер является Global Catalog-ом.</p>
<p>Для полной ясности выясним кто у нас является Администратором, вернее получим список группы Administrators.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="re0">$group</span> <span class="sy0">=</span> Get<span class="sy0">-</span>AdGroup Administrators<br />
Get<span class="sy0">-</span>ADUser <span class="sy0">-</span><span class="kw3">Filter</span> <span class="br0">&#123;</span>MemberOf <span class="sy0">-</span>recursivematch <span class="re0">$group</span>.DistinguishedName<span class="br0">&#125;</span></div>
</div>
<p>Дальше проще.<br />
Смотрим когда пользователь Administrator в последний раз менял пароль.</p>
<pre>Get-ADUser Administrator -properties PasswordLastSet
DistinguishedName : CN=Administrator,CN=Users,DC=LAB,DC=LOCAL
Enabled           : True
GivenName         :
Name              : Administrator
ObjectClass       : user
ObjectGUID        : ed5de06a-265c-43da-ab4e-65f3e09e4c32
PasswordLastSet   : 11.06.2011 12:54:33
SamAccountName    : Administrator</pre>
<p>Выходит что давно <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Изучаем то что имеется дальше и запрашиваем список имеющихся учетных записей компьютеров.</p>
<pre>Get-ADComputer -LDAPFilter "(name=*)"
DistinguishedName : CN=SRV-01,OU=OU=Members Servers,DC=LAB,DC=LOCAL
DNSHostName       : SRV-01.LAB.LOCAL
Enabled           : True
Name              : SRV-01
ObjectClass       : computer
SamAccountName    : SRV-01$
UserPrincipalName :
...</pre>
<p>Для того что бы детально изучить список найденных серверов, берем первый сервер из списка и вводим:</p>
<pre>Get-ADComputer -LDAPFilter "(name=SRV-01)" -properties *

CanonicalName                      : LAB.LOCAL/Members Servers/SRV-01
CN                                 : SRV-01
Created                            : 25.04.2011 11:53:17
Enabled                            : True
IPv4Address                        : 192.168.1.100
IPv6Address                        :
isCriticalSystemObject             : False
LastLogonDate                      : 07.12.2011 6:57:28
Location                           : Site-2
MemberOf                           : {CN=SCOM-MS-02_PrimarySG_2164,CN=LAB,CN=OperationsManager,DC=LAB,DC=LOCAL, CN=SCOM-MS-01_PrimarySG_2164,CN=LAB,CN=OperationsManager,DC=LAB,DC=LOCAL}
msDFSR-ComputerReferenceBL         : {CN=6c3d3b66-923e-4aaa-9cdc-1319aaa6e95c,CN=Topology,CN=DFS-TESTMEDIA,CN=DFSR-GlobalSettings,CN=System,DC=LAB,DC=LOCAL}
Name                               : SRV-01
OperatingSystem                    : Windows Server 2003
OperatingSystemHotfix              :
OperatingSystemServicePack         : Service Pack 2
OperatingSystemVersion             : 5.2 (3790)
PasswordLastSet                    : 03.12.2011 18:23:53
servicePrincipalName               : {Dfsr-12F9A27C-BF97-4787-9162-D31B6C55EB04/SRV-01.LAB.LOCAL, WSMAN/SRV-01, WSMAN/SRV-01.LAB.LOCAL, SMTPSVC/SRV-01.LAB.LOCAL...}</pre>
<p>По прежнему интересно?</p>
<p>Судя по выводу мы имеем Windows 2003 Server, с установленным SP2, на котором имеются следы от DFSr и SMTP, обнаруживается так же присутствие установленного SCOM-а.</p>
<p>Посмотрим список SPN-ов подробнее.</p>
<pre>
(Get-ADComputer -LDAPFilter "(name=SRV-01)" -properties *).servicePrincipalName
</pre>
<p>Содержательно, но надо двигаться дальше. Для полноты картины посмотрим в DefaultDomainPasswordPolicy:</p>
<pre>Get-ADDefaultDomainPasswordPolicy
ComplexityEnabled           : True
DistinguishedName           : DC=lab,DC=local
LockoutDuration             : 00:10:00
LockoutObservationWindow    : 00:10:00
LockoutThreshold            : 5
MaxPasswordAge              : 45.00:00:00
MinPasswordAge              : 0.00:00:00
MinPasswordLength           : 10
objectClass                 : {domainDNS}
objectGuid                  : 515a4469-fda9-4a18-95f9-404da09f3210
PasswordHistoryCount        : 5
ReversibleEncryptionEnabled : False</pre>
<p>Изучим всех пользователей с не-истекающими паролями:</p>
<pre>Get-ADUser -filter {PasswordNeverExpires -eq $True -AND Enabled -eq $True} | Select Distinguishedname
Distinguishedname
-----------------
CN=Administrator,CN=Users,DC=lab,DC=local
CN=user01,CN=TestOU,DC=lab,DC=local
CN=user02,CN=TestOU,DC=lab,DC=local
CN=user03,CN=TestOU,DC=lab,DC=local</pre>
<p>Можно было бы выбрать любое количество свойств для отображения, но нам нужно только одно свойство PasswordLastSet. Немного изменяем команду:</p>
<pre>Get-ADUser -filter {PasswordNeverExpires -eq $True -AND Enabled -eq $True} -properties PasswordLastSet | Sort PasswordLastSet | Select Distinguishedname,PasswordLastSet

Distinguishedname                                      PasswordLastSet
-----------------                                      ---------------
CN=Administrator,CN=Users,DC=lab,...                   1/24/2011 1:20:19 PM
CN=user01,CN=TestOU,DC=lab,DC=local                    1/24/2011 3:20:19 PM
CN=user02,CN=TestOU,DC=lab,DC=local                    1/24/2011 3:20:18 PM
CN=user03,CN=TestOU,DC=lab,DC=local                    1/24/2011 3:20:18 PM</pre>
<p>Теперь считаем учетные записи срок действия паролей для которых истек</p>
<pre>Get-ADUser -filter {Enabled -eq $True} -properties passwordExpired | where {$_.PasswordExpired} | measure-object
Count    : 5
Average  :
Sum      :
Maximum  :
Minimum  :
Property :</pre>
<p>Много и интересно <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  но мало пригодно для использования.</p>
<p>Для комплекта стоит создать отчет об активных аккаунтах у которых не истекает пароль в виде таблички.</p>
<pre>Get-ADUser -filter {Enabled -eq $True -AND PasswordNeverExpires -eq $False} -properties * | Sort PasswordLastSet | Select Name,PasswordLastSet,PasswordExpired,@{Name="PasswordAge";Expression={(Get-Date)-$_.PasswordLastSet}}
Name             PasswordLastSet       PasswordExpired PasswordAge
----             ---------------       --------------- -----------
user04           1/24/2011 3:20:19 PM  False 5.05:23:24.7644101
…</pre>
<p>Как использовать полученные данные решать вам. Уверен что данные выше &laquo;галопом по европе&raquo; рецепты будут использованы только в благих целях.</p>
<p>Какова мораль всего вышесказанного?<br />
Прежде чем кидаться устанавливать сторонние приложения, пусть даже такие удобные и функциональные как PowerGUI, стоит изучить то что уже имеется.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2011/12/powershell-active-directory-module/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Смена ip адресов. Головная боль?</title>
		<link>http://blog.wadmin.ru/2011/12/change-ip-addresses-a-headache/</link>
		<comments>http://blog.wadmin.ru/2011/12/change-ip-addresses-a-headache/#comments</comments>
		<pubDate>Mon, 05 Dec 2011 07:11:51 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Заметки]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=5179</guid>
		<description><![CDATA[Предположим что у вас есть несколько задач имеющих под собою цель смены ip-адресов в некой абстрактной сети. Что первое приходит в голову? У нас есть новый DHCP (старый планируется на снос). У нас есть новые [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-5261" title="network" src="http://blog.wadmin.ru/wp-content/uploads/2011/12/network.jpg" alt="network" width="120" height="90" />Предположим что у вас есть несколько задач имеющих под собою цель смены ip-адресов в некой абстрактной сети.</p>
<p>Что первое приходит в голову?</p>
<ul>
<li>У нас есть новый DHCP (старый планируется на снос).</li>
<li>У нас есть новые DNS-серверы которые вы согласно плану уже развернули.</li>
<li>От Wins-ов мы старательно хотим избавиться, но они унаследованы и пока это не получается и мы обдумываем переход на GlobalNames.</li>
</ul>
<p><em>Примечание: Естественно все это поднято в варианте Server Core на кластере Hyper-V, все это хозяйство уже бэкапится через DPM 2010 ну и т.д. и т.п&#8230;</em></p>
<p>Предположим что у вас есть список хостов, предположим что у вас даже есть схема сети и даже розетки пронумерованы и есть понимание что розетка номер 05-01-12 на кроссе уходит в кабинет такой то.</p>
<p>Если это так то вам несказанно повезло <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Когда вы разобравшись в бумагах, понимаете что часть компьютеров имеют статические адреса, часть получают адреса динамически, что есть компьютеры в рабочей группе, а есть вообще непонятно что т.к. у них по хитрому умыслу разработчиков не прописано ни DNS-а ни шлюза. Одним словом зоопарк. Вы приходите в ужас от перспективы весело провести выходные и мысленно уже считаете сколько пива может понадобится что бы избавится от постэффектов <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>PowerShell в помощь. Да. Да. Именно его.</p>
<p>Для работы нам понадобится класс .NET - <strong>[System.Net.Dns]::GetHostAddresses()</strong> и немного терпения<strong>.</strong></p>
<p>Разрешение имени в адрес происходит следующим образом.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="br0">&#91;</span>System.Net.DNS<span class="br0">&#93;</span>::GetHostAddresses<span class="br0">&#40;</span><span class="st0">&quot;yandex.ru&quot;</span><span class="br0">&#41;</span></div>
</div>
<p>Обратное преобразование выполняется так</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="br0">&#91;</span>System.Net.DNS<span class="br0">&#93;</span>::GetHostByAddress<span class="br0">&#40;</span><span class="st0">&quot;77.88.21.3&quot;</span><span class="br0">&#41;</span></div>
</div>
<p>На практике это будет выглядеть примерно так.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="re0">$ServerName</span> <span class="sy0">=</span> <span class="st0">&quot;HOST_NAME&quot;</span><br />
<span class="br0">&#91;</span>System.Net.Dns<span class="br0">&#93;</span>::GetHostAddresses<span class="br0">&#40;</span><span class="re0">$ServerName</span><span class="br0">&#41;</span><br />
<span class="co1"># или обратное преобразование</span><br />
<span class="re0">$IP</span> <span class="sy0">=</span> <span class="st0">&quot;192.168.0.1&quot;</span><br />
<span class="br0">&#91;</span>System.Net.Dns<span class="br0">&#93;</span>::GetHostEntry<span class="br0">&#40;</span><span class="re0">$IP</span><span class="br0">&#41;</span></div>
</div>
<p>Но перебирать имена из имеющегося списка и адреса довольно скучно и очень хочется <a title="Быстрое создание hostlist.txt" href="http://blog.wadmin.ru/2011/11/create-hostlist-file/">создать актуальный список адресов</a> и использовать его для дальнейших исследований.</p>
<p>Список получен. Что дальше?</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="co1"># берем данные из файла</span><br />
<span class="re0">$hosts</span> <span class="sy0">=</span> <span class="kw1">Get-Content</span> servers.txt<br />
<span class="co1"># если файла нет то задаем список адресов</span><br />
<span class="co1">#hosts = &quot;192.168.0.1&quot;,&quot;192.168.0.2&quot;,&quot;192.168.0.3&quot;</span></p>
<p><span class="co1"># создадим пустой массив для результатов</span><br />
<span class="re0">$ResultList</span> <span class="sy0">=</span> <span class="sy0">@</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="co1"># в цикле разрешаем имена</span><br />
<span class="kw3">foreach</span> <span class="br0">&#40;</span><span class="re0">$hostname</span> <span class="kw3">in</span> <span class="re0">$hosts</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$result</span> <span class="sy0">=</span> <span class="re0">$null</span><br />
<span class="re0">$currentEAP</span> <span class="sy0">=</span> <a href="about:blank"><span class="kw6">$ErrorActionPreference</span></a><br />
<a href="about:blank"><span class="kw6">$ErrorActionPreference</span></a> <span class="sy0">=</span> <span class="st0">&quot;silentlycontinue&quot;</span></p>
<p><span class="re0">$result</span> <span class="sy0">=</span> <span class="br0">&#91;</span>System.Net.Dns<span class="br0">&#93;</span>::gethostentry<span class="br0">&#40;</span><span class="re0">$hostname</span><span class="br0">&#41;</span></p>
<p><a href="about:blank"><span class="kw6">$ErrorActionPreference</span></a> <span class="sy0">=</span> <span class="re0">$currentEAP</span><br />
<span class="kw3">If</span> <span class="br0">&#40;</span><span class="re0">$Result</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$Resultlist</span> <span class="sy0">+=</span> <span class="st0">&quot;$($Result.HostName) &#8211; $($Result.AddressList)&quot;</span><br />
<span class="br0">&#125;</span> <span class="kw3">Else</span> <span class="br0">&#123;</span><br />
<span class="re0">$Resultlist</span> <span class="sy0">+=</span> <span class="st0">&quot;$IP &#8211; No HostNameFound&quot;</span><br />
<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<span class="co1"># выводим результаты в файл</span><br />
<span class="re0">$resultlist</span> <span class="sy0">|</span> <span class="kw1">Out<span class="kw4">-File</span></span> output.txt</div>
</div>
<p>Когда вы начинаете понимать что проще застрелиться чем понять что происходит вы натыкаетесь на мысть &#8211; &laquo;А не скачать ли мне nmap?&raquo;</p>
<p>Я же предлагаю не впадать в крайности и прибегнуть к помощи все того же PowerShell-а. Теперь проходим по диапазонам адресов.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><a href="about:blank"><span class="kw6">$ErrorActionPreference</span></a> <span class="sy0">=</span> <span class="st0">&quot;SilentlyContinue&quot;</span></p>
<p><span class="co1"># ЗАдаем диапазон для сканирования 1-254</span><br />
1..254 <span class="sy0">|</span> <span class="kw3">foreach</span> <span class="kw5">-Process</span> <span class="br0">&#123;</span><br />
<span class="co1"># создадим объект</span><br />
<span class="re0">$obj</span> <span class="sy0">=</span> <span class="kw1">New-Object</span> PSObject;</p>
<p><span class="re0">$ping</span> <span class="sy0">=</span> <span class="kw1">get-WmiObject</span> <span class="kw5">-Class</span> Win32_PingStatus <span class="sy0">-</span><span class="kw3">Filter</span> <span class="br0">&#40;</span><span class="st0">&quot;Address=&#8217;192.168.0.&quot;</span> <span class="sy0">+</span> <a href="about:blank"><span class="kw6">$_</span></a> <span class="sy0">+</span> <span class="st0">&quot;&#8217;&quot;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$obj</span> <span class="sy0">|</span> <span class="kw1">Add-Member</span> NoteProperty IPAddress<span class="br0">&#40;</span><span class="re0">$ping</span>.Address<span class="br0">&#41;</span>;<br />
<span class="re0">$obj</span> <span class="sy0">|</span> <span class="kw1">Add-Member</span> NoteProperty StatusCode<span class="br0">&#40;</span><span class="re0">$ping</span>.StatusCode<span class="br0">&#41;</span>;</p>
<p><span class="co1"># если хост отвечает</span><br />
<span class="kw3">if</span><span class="br0">&#40;</span><span class="re0">$ping</span>.StatusCode <span class="kw4">-eq</span> 0<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$obj</span> <span class="sy0">|</span> <span class="kw1">Add-Member</span> NoteProperty Status<span class="br0">&#40;</span><span class="st0">&quot;Online&quot;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$dns</span> <span class="sy0">=</span> <span class="br0">&#91;</span>System.Net.Dns<span class="br0">&#93;</span>::GetHostByAddress<span class="br0">&#40;</span><span class="re0">$ping</span>.Address<span class="br0">&#41;</span>;</p>
<p><span class="kw3">if</span><span class="br0">&#40;</span><span class="re0">$dns</span> <span class="kw4">-ne</span> <span class="re0">$null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$obj</span> <span class="sy0">|</span> <span class="kw1">Add-Member</span> NoteProperty ResolvedHostName<span class="br0">&#40;</span><span class="re0">$dns</span>.HostName<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span> <span class="kw3">else</span> <span class="br0">&#123;</span><br />
<span class="re0">$obj</span> <span class="sy0">|</span> <span class="kw1">Add-Member</span> NoteProperty ResolvedHostName<span class="br0">&#40;</span><span class="st0">&quot;&quot;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span> <span class="kw3">else</span> <span class="br0">&#123;</span><br />
<span class="co1"># если хост не отвесает то ставим ему статус offline</span><br />
<span class="re0">$obj</span> <span class="sy0">|</span> <span class="kw1">Add-Member</span> NoteProperty ResolvedHostName<span class="br0">&#40;</span><span class="st0">&quot;&quot;</span><span class="br0">&#41;</span>;<br />
<span class="re0">$obj</span> <span class="sy0">|</span> <span class="kw1">Add-Member</span> NoteProperty Status<span class="br0">&#40;</span><span class="st0">&quot;Offline&quot;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="co1"># выводим результат на экран</span><br />
<span class="kw1">Write-Output</span> <span class="re0">$obj</span><br />
<span class="co1"># или в файл</span><br />
<span class="kw1">Add-content</span> .\result.txt <span class="re0">$obj</span>;</p>
<p><span class="co1"># Чистим за собою</span><br />
<span class="re0">$dns</span> <span class="sy0">=</span> <span class="re0">$null</span>;<br />
<span class="br0">&#125;</span></div>
</div>
<p>После найденных хостов которые используют статические адреса можно немного модифицировать код</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="re0">$NICs</span> <span class="sy0">=</span> <span class="kw1">Get-WmiObject</span> Win32_NetworkAdapterConfiguration <span class="sy0">|</span> <span class="kw3">Where</span> <span class="br0">&#123;</span><a href="about:blank"><span class="kw6">$_</span></a>.IPEnabled <span class="kw4">-eq</span> <span class="st0">&quot;TRUE&quot;</span><span class="br0">&#125;</span><br />
<span class="kw3">foreach</span><span class="br0">&#40;</span><span class="re0">$NIC</span> <span class="kw3">in</span> <span class="re0">$NICs</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$NIC</span>.EnableDHCP<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="re0">$NIC</span>.SetDNSServerSearchOrder<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>Вроде как все собрано, вроде как у нас есть понимание что мы хотим получить в итоге, но не хватает чего то для понимания полной картины&#8230;</p>
<p>Не гадайте. Я отвечу просто &#8211; не хватает списка настроек найденных хостов.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="co1"># задаем имя файла</span><br />
<span class="re0">$hostlist</span> <span class="sy0">=</span> <span class="st0">&quot;servers.txt&quot;</span><br />
<span class="co1"># читаем из него список</span><br />
<span class="re0">$servers</span> <span class="sy0">=</span> <span class="kw1">Get-Content</span> <span class="re0">$hostlist</span><br />
<span class="co1"># вводим учетные данные под которыми будем получать настройки</span><br />
<span class="re0">$credential</span> <span class="sy0">=</span> <span class="kw1">Get-Credential</span></p>
<p><span class="kw3">foreach</span> <span class="br0">&#40;</span><span class="re0">$server</span> <span class="kw3">in</span> <span class="re0">$servers</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$colItems</span> <span class="sy0">=</span> <span class="kw1">Get-WmiObject</span> Win32_NetworkAdapterConfiguration <span class="kw5">-Namespace</span> <span class="st0">&quot;root\CIMV2&quot;</span> <span class="kw5">-ComputerName</span> <span class="re0">$server</span> <span class="kw5">-credential</span> <span class="re0">$credential</span> <span class="kw5">-ErrorAction</span> SilentlyContinue <span class="sy0">|</span> <span class="kw3">where</span><span class="br0">&#123;</span><a href="about:blank"><span class="kw6">$_</span></a>.IPEnabled <span class="kw4">-eq</span> <span class="st0">&quot;True&quot;</span><span class="br0">&#125;</span><br />
<span class="kw3">foreach</span><span class="br0">&#40;</span><span class="re0">$objItem</span> <span class="kw3">in</span> <span class="re0">$colItems</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$str</span> <span class="sy0">=</span> <span class="st0">&quot;$($server); $($objItem.DHCPEnabled); $($objItem.IPAddress); $($objItem.IPSubnet); $($objItem.DefaultIPGateway)&quot;</span><br />
<span class="kw1">Write-Host</span> <span class="re0">$str</span><br />
<span class="kw1">Add-content</span> .\result.txt <span class="re0">$str</span><br />
<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>В этом скрипте стоит обратить внимание на $objItem.DHCPEnabled.</p>
<ul>
<li>True &#8211; указывает на то что хост получает настройки с DHCP.</li>
<li>False &#8211; настройки прописаны руками.</li>
</ul>
<div>В моем случае требовалось заменить адреса WINS-ов и DNS-а. Дописан проверку на True-False я добавил следующий код.</div>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="co1"># задаем список DNS серверов</span><br />
<span class="re0">$DNSServers</span> <span class="sy0">=</span> <span class="st0">&quot;198.100.1.1″,&quot;</span>198.101.1.1″<br />
<span class="re0">$NIC</span>.SetDNSServerSearchOrder<span class="br0">&#40;</span><span class="re0">$DNSServers</span><span class="br0">&#41;</span><br />
<span class="co1"># указываем шлюз по умолчанию</span><br />
<span class="re0">$NIC</span>.SetGateways<span class="br0">&#40;</span><span class="st0">&quot;192.168.0.1″)<br />
# включаем регистрацию<br />
$NIC.SetDynamicDNSRegistration(&quot;</span>TRUE<span class="st0">&quot;)<br />
# задаем новые WINS-ы<br />
$NIC.SetWINSServer(“198.100.1.2″, &quot;</span>198.101.1.2″<span class="br0">&#41;</span></div>
</div>
<p>Если требуется удалить все статические настройки то код меняется на следущий</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="re0">$NIC</span>.EnableDHCP<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="re0">$NIC</span>.SetDNSServerSearchOrder<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</div>
<p>Можно конечно помучится и прописать новую статику как показано ниже, но подумайте о том чтоит ли это делать&#8230;</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="re0">$NIC</span>.EnableStatic<span class="br0">&#40;</span><span class="st0">&quot;192.168.1.42&quot;</span><span class="sy0">,</span> <span class="st0">&quot;255.255.255.0&quot;</span><span class="br0">&#41;</span></div>
</div>
<p>В завершении, было бы неплохо перезагрузить тех кто не хочет это делать или ему просто необходима перезагрузка.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="co1"># список опций</span><br />
<span class="co1"># 0 – Log Off</span><br />
<span class="co1"># 4 – Forced Log Off</span><br />
<span class="co1"># 1 – Shutdown</span><br />
<span class="co1"># 5 – Forced Shutdown</span><br />
<span class="co1"># 2 – Reboot</span><br />
<span class="co1"># 6 – Forced Reboot</span><br />
<span class="co1"># 8 – Power Off</span><br />
<span class="co1"># 12 – Forced Power Off</span><br />
<span class="co1">#</span><br />
<span class="co1"># показываем только – 4, 5, 6 – force logoff of user, force shutdown, 6 force reboot</span><br />
<span class="re0">$computerName</span> <span class="sy0">=</span> <span class="kw1">read-host</span> <span class="st0">&quot;Type the computername or ip address&quot;</span><br />
<span class="re0">$command</span> <span class="sy0">=</span> <span class="kw1">read-host</span> <span class="st0">&quot;Choose the following number:<br />
4 – logoff user<br />
5 – shutdown<br />
6 – reboot&quot;</span><br />
<span class="br0">&#40;</span><span class="kw2">gwmi</span> win32_OperatingSystem <span class="kw5">-ComputerName</span> <span class="re0">$computerName</span><span class="br0">&#41;</span>.Win32Shutdown<span class="br0">&#40;</span><span class="re0">$command</span><span class="br0">&#41;</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2011/12/change-ip-addresses-a-headache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Альтернатива SAPD.exe средствами PowerShell</title>
		<link>http://blog.wadmin.ru/2011/12/reading-lsa-service-account-secrets-using-powershell/</link>
		<comments>http://blog.wadmin.ru/2011/12/reading-lsa-service-account-secrets-using-powershell/#comments</comments>
		<pubDate>Sun, 04 Dec 2011 09:17:48 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Заметки]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Безопасность]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=5250</guid>
		<description><![CDATA[У моего кота есть дурная привычка приходить по утрам, примерно в 06.45, и начинать будить. Происходит это примерно так: Попытка №1 &#8211; вопль прямо в ухо &#171;Хозяяяяин, вставай&#8230;&#187; Если попытка оказалась не успешной то  попытка №2 более [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.wadmin.ru/wp-content/uploads/2011/07/powershell.png"><img class="alignright size-full wp-image-3915" title="powershell" src="http://blog.wadmin.ru/wp-content/uploads/2011/07/powershell.png" alt="powershell" width="128" height="128" /></a>У моего кота есть дурная привычка приходить по утрам, примерно в 06.45, и начинать будить. Происходит это примерно так:</p>
<ul>
<li>Попытка №1 &#8211; вопль прямо в ухо &laquo;Хозяяяяин, вставай&#8230;&raquo;</li>
<li>Если попытка оказалась не успешной то  попытка №2 более эффективна т.к. при ней берется правая лапа, которой сначала без когтей кот аккуратно касается уха. Если результата нет то когти выпускаются на ноль целых хрен десятых миллиметра. Дальше когти длиннее.</li>
</ul>
<p>Достижение задачи  стопроцентное&#8230;</p>
<p>Вы спросите какое отношение мой кот имеет к PowerShell и SAPD.exe?</p>
<p>Отвечу что самое непосредственное т.к. он обожает наблюдать когда я работаю с ISE или консолью powershell. На другие окна реагирует однозначно т.е. ложиться на клавиатуру, мол нефиг ерундой заниматься <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Хотя. я немного отвлекся от тематики. Вернемся во вчерашний день.</p>
<p>Вчера, после просмотра записи <a href="http://www.techdays.ru/videos/3923.html" rel="nofollow">доклада</a> Полы Янушкевич, я подводя итоги погуглил на тему утилиты SAPD.exe (получение паролей от учетных записей сервисов). Нужная страница нашлась сразу же, вот она - <a href="http://waldemar-dacko.blogspot.com/2011/10/sapd-and-service-account-password.html" rel="nofollow">http://waldemar-dacko.blogspot.com/2011/10/sapd-and-service-account-password.html</a>.</p>
<p><em>Примечание: В свое время, у меня была своя реализация этой задачи написанная на VBS  и я решил потестировать <strong>SAPD.exe</strong>.</em></p>
<p>Слил. Поставил. Работает.</p>
<p>Собственно ничего нового в <strong>SAPD.exe</strong> нет. Все настройки хранятся в реестре, если быть точнее то в ветке</p>
<pre>HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets</pre>
<p>Нужный сервис ищется в ветке</p>
<pre>_SC_имя_сервиса</pre>
<p>Которая содержит следующие значения:</p>
<ul>
<li>CurrVal – текущее зашифрованное значение</li>
<li>CupdTime – время последнего обновления</li>
<li>OldVal – старое значение</li>
<li>OupdTime &#8211; время обновления старого значения</li>
<li>SecDesc – дескриптор</li>
</ul>
<p>Для того что бы добраться до ветки</p>
<pre>HKLM:\Security\Policy\Secrets</pre>
<p>Нужно запустить powershell с помощью утилиты psexec</p>
<pre>PsExec.exe -i -s powershell.exe</pre>
<p>Дальше, что называется, счет идет на секунды <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Искать и переписывать на PowerShell имеющийся VBS-скрипт не стал т.к. есть готовое решение на PowerShell, вот <a href="http://www.powershell.nu/2011/08/13/reading-lsa-service-account-secrets-using-powershell/" rel="nofollow">оно</a>.</p>
<p>Результирующие скрипт без каких либо изменений доступен для загрузки <a onclick="_gaq.push(['_trackEvent', 'Download_fle', 'Get-LsaSecret.txt']);" href="http://blog.wadmin.ru/downloads/Get-LsaSecret.txt">тут</a>.</p>
<p>Вывод?</p>
<p>Не стоит запускать сервисы из под аккаунтов с повышенными привилегиями т.к. пароль можно получить не то что бы очень просто, а удивительно быстро <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2011/12/reading-lsa-service-account-secrets-using-powershell/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Быстрое создание hostlist.txt</title>
		<link>http://blog.wadmin.ru/2011/11/create-hostlist-file/</link>
		<comments>http://blog.wadmin.ru/2011/11/create-hostlist-file/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 06:48:12 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Инструменты]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=4880</guid>
		<description><![CDATA[Я неоднократно писал про то что использую в работе файл servers.txt или hostlist.txt, но ни разу не показывал как именно я собираю данные. Вариантов масса &#8211; можно экспортировать данные из оснастки ADUC, можно рисовать руками, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-5055" title="hostlist.txt" src="http://blog.wadmin.ru/wp-content/uploads/2011/11/hostlist.jpg" alt="hostlist.txt" width="120" height="141" />Я неоднократно писал про то что использую в работе файл <strong>servers.txt</strong> или <strong>hostlist.txt</strong>, но ни разу не показывал как именно я собираю данные.</p>
<p>Вариантов масса &#8211; можно экспортировать данные из оснастки ADUC, можно рисовать руками, но лучше скриптом.</p>
<p>Для работы скрипта должен быть установлен модуль Active Directory Module for PowerShell (из пакета RSAT). Естественно запускаться это все должно на Windows 7.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;"><span class="co1"># импортируем модуль ActiveDirectory</span><br />
Import<span class="sy0">-</span>Module ActiveDirectory<br />
<span class="co1"># Указываем путь для поиска</span><br />
<span class="re0">$base</span> <span class="sy0">=</span> <span class="st0">&#8216;OU=Servers,DC=domain,DC=local&#8217;</span><br />
<span class="co1"># на всякий случай берем только свежие записи</span><br />
<span class="re0">$d</span> <span class="sy0">=</span> <span class="br0">&#91;</span>DateTime<span class="br0">&#93;</span>::Today.AddDays<span class="br0">&#40;</span><span class="sy0">-</span><span class="nu0">30</span><span class="br0">&#41;</span><br />
<span class="co1"># выполняем поиск</span><br />
<span class="re0">$computers</span> <span class="sy0">=</span> Get<span class="sy0">-</span>ADComputer <span class="sy0">-</span><span class="kw3">Filter</span> <span class="st0">&#8216;PasswordLastSet -ge $d&#8217;</span> <span class="sy0">-</span>Searchbase <span class="re0">$base</span><br />
<span class="co1"># выводим результаты в файл hostlist.txt</span><br />
<span class="kw3">foreach</span><span class="br0">&#40;</span><span class="re0">$computer</span> <span class="kw3">in</span> <span class="re0">$computers</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="re0">$computer</span>.Name <span class="sy0">|</span> <span class="kw1">Out<span class="kw4">-file</span></span> hostlist.txt <span class="kw5">-append</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>PS уверен что приведенный ниже скрипт можно упростить <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Выкладывайте свои варианты в комментариях.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2011/11/create-hostlist-file/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Зачем нужно подписывать скрипты?</title>
		<link>http://blog.wadmin.ru/2011/09/do-i-need-signed-script/</link>
		<comments>http://blog.wadmin.ru/2011/09/do-i-need-signed-script/#comments</comments>
		<pubDate>Fri, 30 Sep 2011 10:38:05 +0000</pubDate>
		<dc:creator>Сергей Мариничев</dc:creator>
				<category><![CDATA[Заметки]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://blog.wadmin.ru/?p=4683</guid>
		<description><![CDATA[Первой и самой главной ошибкой тех кто начинает работать с PowerShell является запуск представленной ниже команды на всех хостах. Set-ExecutionPolicy Unrestricted Вроде как удобно, но поверьте последствия могут быть самые разнообразные&#8230; Результатом выставления уровня запуска [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-4684" title="Зачем нужно подписывать скрипт" src="http://blog.wadmin.ru/wp-content/uploads/2011/09/sign-script.jpg" alt="Зачем нужно подписывать скрипт" width="150" height="112" /> Первой и самой главной ошибкой тех кто начинает работать с PowerShell является запуск представленной ниже команды на всех хостах.</p>
<blockquote><p>Set-ExecutionPolicy Unrestricted</p></blockquote>
<p>Вроде как удобно, но поверьте последствия могут быть самые разнообразные&#8230;</p>
<p>Результатом выставления уровня запуска в режим <strong>Unrestricted</strong> будет ослабление надежной политики безопасности &laquo;по умолчанию&raquo; и как возможные последствия &#8211; потеря контроля и возможная компроментация учетных записей. Насколько хватит фантазии <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><em>Примечание: Напомню, что по умолчанию высталена безопасная политика Restricted (ничего и никому), об этом я <a title="Уроки Powershell – создаем первый скрипт" href="http://blog.wadmin.ru/2011/08/powershell-lessons-first-script/">недавно писал</a>, надеюсь что вы это читали, а если не читали то обязательно зайдете.</em></p>
<p>Перед тем как поступить опрометчиво подумайте стоит ли оно этого&#8230;</p>
<ul>
<li>Запускаете ли вы скрипты на рабочих станциях? Для каких целей?</li>
<li>Запускаете ли вы их в контексте пользователей имеющих административные привилегии?</li>
<li>Если запускаете то подписаны ли они?</li>
</ul>
<p>Предлагаю рассмотреть следующий сценарий.</p>
<ol>
<li>На всех рабочих станциях <strong>Execution Policy</strong> выставлено в <strong>Unrestricted </strong>(встречаю довольно часто).</li>
<li>В контексте пользователя запускается логон-скрипт ан powershell по подключению принтеров и общих папок, копированию некого набора файлов и пр.</li>
</ol>
<p>Какие минусы?</p>
<p>На первый взгляд все замечательно, все работает, никто не жалуется. Вроде все хорошо т.к. запускаемые скрипты находятся в контролируемой общей папке. Ничего не предвещает проблем, но всегда есть вероятность что они появятся именно в тот момент когда их ожидаешь меньше всего.</p>
<p>Откройте консоль powershell и введите.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">$profile</div>
</div>
<p>Вы получите путь до powershell-профиля пользователя. Редактируем этот файл командой.</p>
<div class="codesnip-container" >
<div class="powershell codesnip" style="font-family:monospace;">notepad $profile</div>
</div>
<p>Открывается файл powershell-профиля для текущего пользователя. Вводим строку &laquo;<strong>Write-Host HELLO!</strong>&laquo;, сохраняем, закрываем. Закрываем консоль powershell, открываем новую. В окне видим надпись <strong>HELLO!</strong></p>
<h3>Что это может дать?</h3>
<p>Первое что приходит в голову &#8211; возможность запускать нужные команды в контексте безопасности пользователя профиль которого надо подменить. Например скопировать файлы с жесткого диска пользователя на нужный ресурс (нет у вас доступа и полномочий а инфу стырить хочется&#8230;) или загрузить файл и выполнить его.</p>
<p><em>Примечание: В случае запуска логон-скрипта то что внесено в Powershell-профиль выполнится автоматически.</em></p>
<p>Подобное возможно в случае если &laquo;Мои документы&raquo; хранятся в папке права на которую выставлены некорректно или удалось подпихнуть заранее созданный файл профиля пользователю под которым планируется зловредная акция <img src='http://blog.wadmin.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Вариантов множество&#8230; Включите фантазию.</p>
<p>Второй вариант подмены профиля может быть реализован в случае если на хосте предоставлены административные полномочия сторонним лицам (внедренцы, аутсорсеры и пр. практика показывает что это бывает довольно часто). В этом варианте конечно существует масса других способов повышения привилегий, но мы пока рассматриваем только подмену powershell-профиля.</p>
<h3>Как бороться.</h3>
<p>Прежде всего нужно определиться где и для чего вы будете использовать PowerShell-скрипты.</p>
<p><em><strong>Мое мнение &#8211; </strong>PowerShell создан для административных задач и запускать его нужно только на доверенных компьютерах. Все остальные задачи можно решать средствами GPO.</em></p>
<p>После понимания области применения необходимо настроить политики запуска только для подписанных скриптов т.к. при попытке подмены файла, скрипт заданный в профиле не будет выполняться.</p>
<h3>Итог</h3>
<p>Вы подписываете скрипты?<br />
Настроены  ли ваши политики на использование только подписанных скриптов?</p>
<p>Что вы думаете по поводу вышесказанного?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.wadmin.ru/2011/09/do-i-need-signed-script/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

