#powershell
#powershell
Вопрос:
Я устраняю проблему в нашей локальной ИТ-инфраструктуре. Некоторое время назад был запущен объект групповой политики, который блокировал трафик от нашей программы ИТ-администрирования к нашим рабочим устройствам.
Короче говоря, крупная компания приняла решение, которое ошибочно влияет на наши очень специфические ИТ-потребности / дизайн в нашем отделе.
По чистой случайности нам удалось решить проблему, вручную добавив исключение безопасности IPSEC на устройстве для решения другой проблемы.
Теперь приведенная ниже хитроумная попытка создать команду PS является лишь основой, поскольку правильные параметры еще предстоит определить после встречи с несколькими сторонами бизнеса и ИТ.
Но чтобы сократить время, необходимое для реализации решения на сотнях наших устройств, я хотел бы, чтобы работал скрипт, в котором мне просто нужно добавить или настроить параметры, когда я получаю слово «go»
Мне нужно, чтобы приведенная ниже команда могла использоваться с вводом (список / массив) всех наших устройств. Я изучаю командлет CimSession, но мне трудно найти решение для перебора списка / массива и добавления в сценарий как целевого компьютера, так и его IP-адреса.
Заранее благодарю вас за советы о том, как действовать дальше.
С помощью приведенных ниже ответов я расширил сценарий до следующего:
```Powershell
# Ask for the csv file
$CsvLocation = Read-Host -Prompt 'input the location of the csv file (for
example c:UsersUSERNAMEDocumentsworkstations.csv)'
$CsvFile = Import-CSV -Path $CsvLocation
# Create empty Hash Table
$Machines = @{Workstation = "Test" ; IP = "123"}
# create a hashtable to store the parameters in for splatting
$ruleParams = @{
Confirm = $false
Enabled = $true
Description = 'This rule is instated to allow MobiControl
Administration to be performed on this device.'
DisplayName = 'MobiControl connection'
IPsecRuleName = 'Mobicontrol connection'
OutboundSecurity = 'None'
InboundSecurity = 'None'
Platform = '6.1 '
PolicyStore = 'PersistentStore'
Profile = 'Any'
RemoteAddress = '10.133.120.207'
RequireAuthorization = $false
Protocol = 'any'
}
# For each Element in the csv file add name and ip address to the hash
table
$CsvFile | ForEach-Object {
$Workstation = $_.Workstation
$IpAddress = [System.Net.Dns]::GetHostAddresses($Workstation) |
Where-Object { $_.AddressFamily -eq 'InterNetwork' } | Select-Object -
ExpandProperty IpAddressToString
$Machines.add($Workstation, $IpAddress)
# fill in the two remaining parameters with the IP address and computer
name
<# test print contents
Read-Host "press enter to see the values for hostname and ip address"
Echo $Machines.keys
Read-Host "press enter to continue"
#>
$ruleParams['LocalAddress'] = $_.Value # IP Address
$ruleParams['CimSession'] = $_.Key # HostName
# execute using the ruleParams splat
Write-Host "Creating IPsecRule on computer $() with IP address $()"
# New-NetIPsecRule @ruleParams
}
Похоже, это больше в нужном мне направлении. Какие-либо очевидные недостатки? входной файл csv будет просто списком имен рабочих станций.
Тестирование кода, похоже, все в рабочем состоянии вплоть до выполнения New-NetIPsecRule. Значения внутри хэш-таблицы $Machines являются недопустимыми входными данными для связанных с ними параметров.
Комментарии:
1. Возможно, вы можете создать хеш-таблицу, где каждый ключ является IP-адресом, а его значение — именем компьютера.
$machines = @{ '10.133.120.207' = 'PC-01'; '10.133.120.211' = 'PC-02'}
и т.д. Затем вы можете выполнить цикл, используя$machines.GetEnumerator() | ForEach-Object {..}
внутри этого цикла, каждый$_.Key
содержит IP-адреса, которые вы можете использовать для параметра-RemoteAddress
, а каждый$_.Value
— соответствующее имя компьютера, которое вы можете установить для параметра-CimSession
2. @Theo Большое вам спасибо, это действительно помогло мне в моих усилиях по созданию рабочего скрипта
Ответ №1:
Способ добавления параметров в командлет неверен и потребует ненавистных обратных меток в конце каждой строки, перед которыми ставится пробел.
Аналогично, но гораздо лучше использовать Splatting
# create a hashtable to store the parameters in for splatting
$ruleParams = @{
Confirm = $false
Enabled = $true
Description = 'This rule is instated to allow MobiControl Administration to be performed on this device.'
DisplayName = 'MobiControl connection'
IPsecRuleName = 'Mobicontrol connection'
OutboundSecurity = 'None'
InboundSecurity = 'None'
Platform = '6.1 '
PolicyStore = 'PersistentStore'
Profile = 'Any'
RemoteAddress = '10.133.120.207'
RequireAuthorization = $false
# I'm not sure about the Protocol parameter..
# The docs say it is a String, but also refer to the Get-NetFirewallPortFilter
# cmdlet where this parameter is a string array (String[])
Protocol = 'TCP,UDP'
}
# now iterate over the $machines hashtable, fill in the two missing parameters in the hash and execute
$machines.GetEnumerator() | ForEach-Object {
$CimSession = Get-CimSession -ComputerName $_.Key
# fill in the two remaining parameters with the IP address and computer name
$ruleParams['LocalAddress'] = $_.Value # IP Address
$ruleParams['CimSession'] = $CimSession
# execute using the ruleParams splat
Write-Host "Creating IPsecRule on computer $($_.Key) with IP address $($_.Value)"
New-NetIPsecRule @ruleParams
$CimSession | Remove-CimSession
}
Отказ от ответственности.. Я не могу попробовать это сам, и поскольку я не уверен Protocol
, что параметром должна быть строка, разделенная запятыми, или массив строк, пожалуйста, сначала попробуйте это на ограниченном тестовом наборе машин.
PS При создании хэш-таблицы $machines измените эту строку
$IpAddress = [System.Net.Dns]::GetHostAddresses($Workstation) |
Where-Object { $_.AddressFamily -eq 'InterNetwork' } | select IpAddressToString
в
$IpAddress = [System.Net.Dns]::GetHostAddresses($Workstation) |
Where-Object { $_.AddressFamily -eq 'InterNetwork' } | Select-Object -ExpandProperty IpAddressToString
Комментарии:
1. спасибо за советы, меня продолжает удивлять, насколько более чистым и эффективным выглядит код, когда он написан людьми, которые действительно знают, что они делают. Я сам немного почистил код после того, как понял, что мне не нужно использовать 2 списка. единственная оставшаяся проблема — это 2 значения, используемые для localAddress и CimSession.
2. @krieksken Я действительно не понимаю.. При первом запуске цикла ForEach-Object элементы для localAddress и CimSession добавляются в хэш-таблицу $ruleParams (splat). На всех последующих итерациях ключ и значение перезаписываются новыми IP и именем хоста, поэтому все элементы в хэш-таблице $machines используются один за другим.
3. Действительно, код для ввода значений в параметры: $ruleParams[‘localAddress’] = $_.Value # IP-адрес $ruleParams[‘CimSession’] = $_.Key # HostName должен работать, но содержимое $ _.Value и ключа недопустимы при попыткеиспользуйте их в качестве параметра
4. параметр Cimsession требует ввода объекта (созданного с помощью New-CimSession) и параметра, в котором я сохраняю IP-адрес, когда я повторяю его, он выдает @{IPAddressToString=10.133.148.147} вместо просто IP-адреса.
5. @krieksken Сделайте
Select-Object -ExpandProperty IpAddressToString
, где вы создаете хэш-таблицу $Machines. Для CimSession, как я вижу, вы также можете использовать Get-CimSession . В цикле попробуйте$CimSession = Get-CimSession -ComputerName $_.Key; $ruleParams['CimSession'] = $CimSession
затем после New-IPSecRule снова уничтожить его с помощью$CimSession | Remove-CimSession