Feeds:
Записи
Комментарии

Archive for Август 2017

Цель нашей лабораторной получить сертификат от доверенного центра сертификации для Skype For Business 2015:
    1. Выбор доверенного центра сертификации
        . Let’s Encrypt
    2. Выбрать способ проверки для получения сертификата
        . Windows DNS Server / Yandex PDD
    3. Определить список доменов в сертификате
        . sfb.contoso.ru,lyncdiscoverinternal.contoso.ru,web.contoso.ru,contoso.ru
    4. Получить сертификат
        . ACMESharp
        . DNSServer module
        . Yandex API
    5. Установить сертификат на сервер Skype For Business 2015
        . Import-CsCertificate
        . Set-CsCertificate
        . Get-CsCertificate

* В сертификате от Let’s Encrypt отсутствует CRL , поэтому может возникнуть проблема с запуском сервиса Fabric и требуется исправление ключа — <Parameter Name=”CrlCheckingFlag” Value=”0”

  https://itbasedtelco.wordpress.com/2016/06/14/s4b-front-end-servers-event-4097-flooding/

 

1. Выбор доверенного центра сертификации

Центры сертификации WoSign и StartCom, которые ранее выдавали сертификаты с большим сроком действия от 1 до 3 лет, перестали быть доверенными компанией Microsoft (https://blogs.technet.microsoft.com/mmpc/2017/08/08/microsoft-to-remove-wosign-and-startcom-certificates-in-windows-10/) и многими другими, хотя возможность получения и покупка сертификатов возможна.
К счастью, есть доверенный центр сертификации
Let’s Encrypt. Его функционала будет достаточно, для создания федерации с другими партнерами и взаимодействия с сервисом Skype. Для взаимодействия с облачными сервисами, требуется дополнительное тестирование.

Let’s Encrypt:
    Стоимость                            — бесплатно
    Сертификат действителен  — 90 дней
    SAN                                  — 100 доменов
    CRL                                   — не поддерживается
    OCSP                                — поддерживается
    IDN(Internationalized Domain Names) — поддерживается
    OV,EV                               — не поддерживается
    Способ проверки             — ftp,http,dns
    RSA размер ключа            — по умолчанию 2048 (2048, 3072, 4096)
    WildCard                            —
https://letsencrypt.org/2017/07/06/wildcard-certificates-coming-jan-2018.html
    Список ограничений       — https://letsencrypt.org/docs/rate-limits/

Список совместимости:
   
https://community.letsencrypt.org/t/which-browsers-and-operating-systems-support-lets-encrypt/4394
    https://letsencrypt.org/docs/certificate-compatibility/

Сроки реализации новых функций:
   
https://letsencrypt.org/upcoming-features/

# IDN (Internationalized Domain Names)             
[System.Globalization.IdnMapping]::new().GetAscii("президент.рф")            
xn--d1abbgf6aiiy.xn--p1ai                
            
[System.Globalization.IdnMapping]::new().GetUnicode("xn--d1abbgf6aiiy.xn--p1ai")            
президент.рф            

2. Выбрать способ проверки для получения сертификата

В данной лабораторной работе, для простоты был выбран способ проверки через записи DNS.

Рассмотрим вариант создания записей в бесплатном сервисе Яндекс.Почта(предоставляет функционал DNS сервера) и Windows DNS Server(должен быть опубликован в интернет).

Кому лень использовать скрипты, может с легкостью получить сертификаты через онлайн сервис — https://www.sslforfree.com/

Windows DnsServer Module — https://technet.microsoft.com/en-us/itpro/powershell/windows/dnsserver/dnsserver

    Get-DnsServerResourceRecord — https://technet.microsoft.com/en-us/itpro/powershell/windows/dnsserver/get-dnsserverresourcerecord

    Add-DnsServerResourceRecord — https://technet.microsoft.com/en-us/itpro/powershell/windows/dnsserver/add-dnsserverresourcerecord

    Set-DnsServerResourceRecord — https://technet.microsoft.com/en-us/itpro/powershell/windows/dnsserver/set-dnsserverresourcerecord

Yandex API Управление DNS — https://tech.yandex.ru/pdd/doc/concepts/api-dns-docpage/

    GET  /api2/admin/dns/list? — Получить DNS-записи домена —
https://tech.yandex.ru/pdd/doc/reference/dns-list-docpage/

    POST /api2/admin/dns/add   — Добавить DNS-запись        — https://tech.yandex.ru/pdd/doc/reference/dns-add-docpage/

    POST /api2/admin/dns/edit  — Редактировать DNS-запись   — https://tech.yandex.ru/pdd/doc/reference/dns-edit-docpage/

Как подключить себе сервис Яндекса:

   
https://blog.it-kb.ru/2016/02/03/delegating-dns-domain-to-yandex-ns-servers-and-connect-to-free-services-yandex-mail-for-domain-with-1000-unlimited-mailboxes-and-yandex-disk/

Все DNS записи будут типа TXT, формата:

name                       class  rr    text

_acme-challenge.domain   IN     TXT   "123drNmQL5vX0bu4YZlgy5wKNBlCny4yrjF1lSaUndc"

 

3. Определить список доменов в сертификате

Требования к сертифакату для Skype For Business 2015 —
https://technet.microsoft.com/en-us/library/dn933910.aspx

Воспользуемся мастером и скопируем список из вкладки Subject Alternative Name — https://blogs.technet.microsoft.com/uclobby/2015/05/15/renewing-skype-for-business-server-2015-certificates/

4. Получить сертификат

К этому пункту у нас должна быть собрана информация:

    + $DomainName    = "contoso.ru"

    + $SAN           = "sfb.contoso.ru","lyncdiscoverinternal.contoso.ru","web.contoso.ru","contoso.ru"

    + $email         = "pki@contoso.ru"

    * Yandex API — учетные данные, зарегистрированный и настроенный домен

+ — Обязательные параметры

* — Необязательные параметры

! — Все действия выполняем под учетной записью с правами Администратора

Для работы с Let’s Encrypt с помощью PowerShell , есть замечательный модуль ACMESharp.

Документация по модулю — https://pkisharp.github.io/ACMESharp-docs/

User Guide: ACMESharp PowerShell Client  — https://pkisharp.github.io/ACMESharp-docs/User-Guide.html

Quick Start: ACMESharp PowerShell Client — https://pkisharp.github.io/ACMESharp-docs/Quick-Start.html

ACMESharp создает Vault , которое содержит очень чувствительные данные.

* https://github.com/ebekker/ACMESharp/wiki/Vaults,-Vault-Providers-and-Vault-Profiles

:sys — the default system-wide Vault if you are running as an elevated user (admin)

    %ALLUSERSPROFILE%\ACMESharp\sysVault

:user — the default user-specific Vault if you are running as a non-elevated user

    %LOCALAPPDATA%\ACMESharp\userVault

Папки:

VAULT  /**/ = "00-VAULT"; // Vault Info

MTADT  /**/ = "01-MTADT"; // Asset Meta Data

PRVDR  /**/ = "10-PRVDR"; // Challenge Handler Provider Profile

INSTP  /**/ = "18-INSTP"; // Installer Provider Profile

CSRDT  /**/ = "30-CSRDT"; // CSR Generation Details

KEYGN  /**/ = "40-KEYGN"; // Private Key Generation Details

KEYPM  /**/ = "45-KEYPM"; // Private Key PEM Export

CSRGN  /**/ = "50-CSRGN"; // CSR Export

CSRPM  /**/ = "55-CSRPM"; // CSR PEM Export

CSRDR  /**/ = "56-CSRDR"; // CSR DER Export

CRTPM  /**/ = "65-CRTPM"; // Certificate PEM Export

CRTDR  /**/ = "66-CRTDR"; // Certificate DER Export

ISUPM  /**/ = "75-ISUPM"; // Issuer Certificate PEM Export

ISUDR  /**/ = "76-ISUDR"; // Issuer Certificate DER Export

ASSET  /**/ = "99-ASSET"; // Generic Asset

vault

Т.к. по умолчанию используется  EFS для защиты Vault ,а у тех где данный функционал отключен , надо будет явно отключить в файле конфигурации EFS — https://pkisharp.github.io/ACMESharp-docs/Local-Vault-EFS.html .

public string RootPath

        { get; set; }

public bool CreatePath

        { get; set; }

public bool BypassEFS

        { get; set; }

 

$param = (Get-ACMEVaultProfile).VaultParameters            
$param.Add("BypassEFS",$true)            
Set-ACMEVaultProfile -ProfileName ":user" -Provider local -VaultParameters $param  -Force

 

{

  "$type": "ACMESharp.Vault.Profile.VaultProfile, ACMESharp.Vault",

  "Name": "user",

  "ProviderName": "local",

  "ProviderParameters": null,

  "VaultParameters": {

    "$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib",

    "BypassEFS": true,

    "CreatePath": true,

    "RootPath": "C:\\Users\\Administrator\\AppData\\Local\\ACMESharp\\userVault"

  }

}

 

Шаг 1: Установка модуля ACMESharp

Install-Module -Name ACMESharp -AllowClobber            
            

Данный модуль располагается в двух репозитариях PSGallery и Nuget. Версия в PSGallery новее и на момент написания 0.9.0.321:

Install-Module -Name ACMESharp -AllowClobber -Repository PSGallery -Force

Шаг 2: Инициализация хранилища

Initialize-ACMEVault
iv_25082017_1

Шаг 3: Регистрация аккаунта

* Let’s Encrypt CA поддерживает только тип email contact, URI формата mailto:<email-address>

New-ACMERegistration -Contacts mailto:$emailAcceptTos

Шаг 4: Подтверждение владением записей домена

В ACMESharp реализовано два типа ChallengeType: dns-01 , http-01 .

https-01 — описан https://pkisharp.github.io/ACMESharp-docs/Quick-Start.html

 

PS > Get-ACMEChallengeHandlerProfile -ListChallengeTypes

dns-01

http-01

PS > Get-ACMEChallengeHandlerProfile -ListChallengeHandlers

manual

Длинная запись:

 

New-ACMEIdentifier -Dns lyncdiscoverinternal.contoso.ru -Alias sfb1            
New-ACMEIdentifier -Dns sfb.contoso.ru -Alias sfb2            
New-ACMEIdentifier -Dns web.contoso.ru -Alias sfb3            
New-ACMEIdentifier -Dns contoso.ru -Alias sfb4            
            
Complete-ACMEChallenge -IdentifierRef sfb1 -ChallengeType dns-01 -Handler manual            
Complete-ACMEChallenge -IdentifierRef sfb2 -ChallengeType dns-01 -Handler manual            
Complete-ACMEChallenge -IdentifierRef sfb3 -ChallengeType dns-01 -Handler manual            
Complete-ACMEChallenge -IdentifierRef sfb4 -ChallengeType dns-01 -Handler manual             
            
Submit-ACMEChallenge -IdentifierRef sfb1 -ChallengeType dns-01            
Submit-ACMEChallenge -IdentifierRef sfb2 -ChallengeType dns-01            
Submit-ACMEChallenge -IdentifierRef sfb3 -ChallengeType dns-01            
Submit-ACMEChallenge -IdentifierRef sfb4 -ChallengeType dns-01            
            
## Give it a minute, just in case -- or go get more coffee            
 sleep -s 60            
            
Update-ACMEIdentifier -IdentifierRef sfb1            
Update-ACMEIdentifier -IdentifierRef sfb2            
Update-ACMEIdentifier -IdentifierRef sfb3            
Update-ACMEIdentifier -IdentifierRef sfb4

 

Короткая запись:

$SAN | Foreach-Object {$i=1} {            
 $id = "sfb$i"            
 New-ACMEIdentifier -Dns $_ -Alias $id | Out-Null            
 Complete-ACMEChallenge -IdentifierRef $id -ChallengeType dns-01 -Handler manual            
 $i++            
}
# Содержит ресурсные записи, которые потребуется создать на DNS сервере            
# Требуются для подтверждения владением доменом            
$DNS = (Get-ACMEVault).Identifiers.Where{$_.Alias -like "sfb*"}.Authorization.Challenges.Where{$_.Type -eq "dns-01"}.Challenge            
chdns_25082017_1            
# Создаем ресурсные записи             
# Windows DNS Server            
$AllRecords = (Get-DnsServerResourceRecord -ZoneName $DomainName -RRType Txt).Where{$_.Name -match "_acme-challenge"}            
            
$DNS.Foreach{            
 $rdns = $_            
 $name = $_.RecordName.TrimEnd($DomainName)            
 $record = $AllRecords.Where{$_.HostName -eq $name}            
 if($record)            
 {            
  $newrecord = $record.Clone()            
  $newrecord.RecordData.DescriptiveText = $_.RecordValue            
  Set-DnsServerResourceRecord -ZoneName $DomainName -NewInputObject $newrecord -OldInputObject $record            
 }            
 else            
 {            
  ADD-DnsServerResourceRecord -ZoneName $DomainName -Txt -Name $name -DescriptiveText $_.RecordValue            
 }            
}
# Yandex API            
Function Input-Captcha            
{            
 Param($src)            
             
 Add-Type -AssemblyName System.Windows.Forms,System.Drawing            
            
 $bimg  = [Net.WebClient]::new().DownloadData($src)            
 $ms    = [IO.MemoryStream]::new($bimg)            
 $img   = [Drawing.Image]::FromStream($ms)            
            
 [Windows.Forms.Application]::EnableVisualStyles();            
             
 $form = New-Object Windows.Forms.Form -Property @{            
  Text            = "Captcha"            
  Width           = 300            
  Height          = 227            
  FormBorderStyle = "FixedDialog"            
  Icon            = [Drawing.Icon]::ExtractAssociatedIcon(            
   "$env:ProgramFiles\Internet Explorer\iexplore.exe"            
  )            
 }            
             
 $pictureBox = New-Object Windows.Forms.PictureBox -Property @{            
  Width    = $img.Size.Width            
  Height   = $img.Size.Height            
  Location = New-Object Drawing.Size(60,30)            
  Image    = $img            
 }            
             
 $button = New-Object Windows.Forms.Button -Property @{            
  Location = New-Object Drawing.Size(12,153)            
  Size     = New-Object Drawing.Size(260,23)            
  Text     = "Set"            
 }            
             
 $button.Add_Click({            
  $script:rep = $textbox.Text.Trim()            
  $form.Close()            
 })            
            
 $textbox = New-Object Windows.Forms.TextBox -Property @{            
  Location = New-Object Drawing.Size(12,117)             
  Size     = New-Object Drawing.Size(260,20)             
 }            
             
 $form.Controls.Add($pictureBox)            
 $form.Controls.Add($button)            
 $form.Controls.Add($textbox)             
 $form.Add_Shown( { $form.Activate() } )            
 $form.ShowDialog() | Out-Null            
}            
            
Function Get-Token            
{            
 [CmdLetBinding()]            
 Param(            
  [String]$Url    = "https://pddimp.yandex.ru",            
  [String]$TUrl   = "https://pddimp.yandex.ru/api2/admin/get_token",            
  [Parameter(Mandatory)]            
   [PSCredential]$Credential,            
  [Parameter(Mandatory)]            
   [String]$DomainName            
 )            
             
 try {            
  # Логинемся в Yandex Passport            
  $wr = Invoke-WebRequest $TUrl -SessionVariable ya            
              
  # В форме заполняем login&passwd            
  $Form = $wr.Forms[0]            
  $Form.Fields["login"]  = $Credential.UserName            
  $Form.Fields["passwd"] = $Credential.GetNetworkCredential().Password            
              
  if($Form)            
  {            
   # Отправляем Post запрос            
   $wr = Invoke-WebRequest -Uri $Form.Action -WebSession $ya -Method POST -Body $Form            
               
   # Если успешно, то переходим к странице получения токена            
   $wr = Invoke-WebRequest $TUrl -WebSession $ya            
   if($wr.ParsedHtml.Title -eq "Admin's token management")            
   {            
    $Form = $wr.Forms[0]            
                
    # Удаляем из post запроса token_del             
    $Form.Fields.Remove("token_del") | Out-Null            
                
    # Вводим капчу            
    Input-Captcha $wr.Images.src            
                
    # Заполняем форму rep - Captcha            
    $Form.Fields["rep"]         = $rep             
    $Form.Fields["domain_name"] = $DomainName            
                
    # Отправляем Post запрос с методом token_get            
    $wr=Invoke-WebRequest -Uri "$url$($Form.Action)" -WebSession $ya -Method POST -Body $Form            
                
    # Возвращаем полученный токен            
    $wr.ParsedHtml.getElementsByTagName("Strong").Item(0).outerText            
   }            
  }            
 }            
 catch {            
  $_            
 }            
}            
            
$LUrl = 'https://pddimp.yandex.ru/api2/admin/dns/list?domain={0}' -f $DomainName            
$EUrl = 'https://pddimp.yandex.ru/api2/admin/dns/edit'            
$AUrl = 'https://pddimp.yandex.ru/api2/admin/dns/add'            
            
$PddToken = Get-Token -Credential "" -DomainName $DomainName            
            
if($PddToken)            
{            
 # Получим все записи для дальнейшего сравнения            
 $AllRecords = Invoke-WebRequest $LUrl -Headers @{            
  "accept" = "application/json"            
  PddToken = $PddToken            
 } | Foreach Content | ConvertFrom-Json | Foreach {$_.Records}            
             
 $DNS | Foreach {            
  $rdns = $_            
  $record = $AllRecords.Where{$_.FQDN -eq $rdns.RecordName}             
  if($record) {            
   # Обновляем данные            
   Invoke-WebRequest $EUrl -Headers @{"accept"="application/json" ; PddToken = $PddToken} -Method POST -Body @{            
    'domain'=$DomainName            
    'record_id'=$record.record_id            
    'content'=$rdns.RecordValue            
   }            
  }            
  else {            
   # Создаем записи            
   Invoke-WebRequest $AUrl -Headers @{"accept"="application/json" ; PddToken = $PddToken} -Method POST -Body @{            
    'domain'=$DomainName            
    'type'='TXT'            
    'subdomain' = $rdns.RecordName.TrimEnd($DomainName)            
    'content'=$rdns.RecordValue            
   }            
  }            
 }            
} 
 
Т.к. для подтверждения требуется вводить captcha вручную.
captcha_25082017_2           
 
# Отправить запрос на проверку            
(Get-ACMEIdentifier).Where{$_.Alias -match "sfb"}.Foreach{Submit-ACMEChallenge -IdentifierRef $_.Alias -ChallengeType dns-01}            
sleep -s 60            
(Get-ACMEIdentifier).Where{$_.Alias -match "sfb"}.Foreach{Update-ACMEIdentifier -IdentifierRef $_.Alias}

uacme_25082017_1

 

Шаг 5. Генерация сертификата

$idref = (Get-ACMEIdentifier).Where{$_.Alias -match "sfb"} | Select -First 1 | Foreach {$_.Alias}            
$aref =  (Get-ACMEIdentifier).Where{$_.Alias -match "sfb"} | Select -Skip 1 | Foreach {$_.Alias}            
New-ACMECertificate -Generate -IdentifierRef $idref -AlternativeIdentifierRefs $aref -Alias SfB2015FECert

new_25082017_1

# Отправить запрос            
Submit-ACMECertificate -CertificateRef SfB2015FECert

submit_25082017_1

Update-ACMECertificate -CertificateRef SfB2015FECert

update_25082017_1

 

Шаг 6. Экспорт в PFX

Get-ACMECertificate SfB2015FECert -ExportPkcs12 "SfB2015FECert.pfx" -CertificatePassword '12345678'
 
5. Установить сертификат на сервер Skype For Business 2015
 
Пример можно посмотреть - https://www.tbs-certificates.co.uk/FAQ/en/install-skype-business-server.html
 
Import-CsCertificate -Path "c:\SfB2015FECert.pfx" -PrivateKeyExportable $True -Password '12345678'            
Set-CsCertificate -Type Default, WebServicesInternal, WebServicesExternal,OAuthTokenIssuer -Thumbprint "439637470DF2D0E9DF933EADEA1F0610B3BA841C"            
            
Get-CsCertificate | Ft Thumbprint,Use            

Thumbprint                               Use
----------                               ---
439637470DF2D0E9DF933EADEA1F0610B3BA841C Default
439637470DF2D0E9DF933EADEA1F0610B3BA841C WebServicesInternal
439637470DF2D0E9DF933EADEA1F0610B3BA841C WebServicesExternal
439637470DF2D0E9DF933EADEA1F0610B3BA841C OAuthTokenIssuer

PS. Скрипты к статье:

le_windows_dns.txt -  Пример для Windows DNS Server

le_yandex_dns.txt    — Пример использования Yandex API PDD

Реклама

Read Full Post »

В Windows 10 Version 1607 / Windows Server 2016 Microsoft добавили новый WMI провайдер WUAProvider для работы с обновлениями, который значительно облегчает  автоматизацию установки обновлений в Nano Server и при удаленном использовании интерфейса Windows Update Agent (ранее приходилось использовать PsExec/Task Scheduler). В предыдущих версиях ОС можно воспользоваться отличным модулем PSWindowsUpdate, для установки:

Install-Module PSWindowsUpdate -Scope AllUsers -Force

Список кодов возврата:

https://gist.github.com/AACJ/48a019ba0708a92d4ba60cc202d55e47

UpdateID:

https://www.catalog.update.microsoft.com

wu_22082017

В версиях Windows до Windows Server 2016, изменить значение Update можно:

# 0 - "Not configured"            
# 1 - "Disabled"            
# 2 - "Notify before download"            
# 3 - "Notify before installation"            
# 4 - "Scheduled installation"            
                     
$WUSettings = (New-Object -ComObject Microsoft.Update.AutoUpdate).Settings.NotificationLevel            
$WUSettings.NotificationLevel=2            
$WUSettings.Save()

Данный метод(SET) не работает в Windows Server 2016 (только GET) и можно воспользоваться изменением настроек через реестр/GPO/sconfig и т.д:

# HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU            
            
# AUOptions	Reg_DWORD             
# 2 = извещать перед загрузкой;            
# 3 = автоматически загружать и оповещать об установке;            
# 4 = автоматически загружать и начинать установку по расписанию (только при задании параметров scheduledDay и SheduledInstallTime);            
# 5 = требуется Automatic Updates, но пользователь может выполнить настройку самостоятельно            
            
# NoAutoUpdate Reg_DWORD            
# 0 = включить Automatic Updates;             
# 1 = отключить Automatic Updates            
            
Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU -Name AUOptions -Value 3

WUAProvider на данный момент документирован не полностью. Основной класс для работы MSFT_WUOperationsSession в котором реализовано 9 методов:

$wu = Get-CimClass -Namespace root/Microsoft/Windows/WindowsUpdate -ClassName MSFT_WUOperationsSession            
$wu.CimClassMethods            
            

Name                     ReturnType Parameters
----                     ---------- ----------
SetCallerID                  UInt32 {CallerID}
ApplyApplicableUpdates       UInt32 {HResult}
ScanForUpdates               UInt32 {OnlineScan, SearchCriteria, HResult, Updates}
ScanForUpdatesWithProxy      UInt32 {BypassList, BypassLocal, ProxyAddress, SearchCriteria...}
DownloadUpdates              UInt32 {Updates, HResult}
DownloadUpdatesWithProxy     UInt32 {BypassList, BypassLocal, ProxyAddress, Updates...}
InstallUpdates               UInt32 {Updates, HResult}
UninstallUpdates             UInt32 {Updates, HResult}
CheckWUOperationState        UInt32 {operationState}
 
# Поиск доступных обновлений - ScanForUpdates            
$ci = New-CimInstance -Namespace root/Microsoft/Windows/WindowsUpdate -ClassName MSFT_WUOperationsSession              
$result = $ci | Invoke-CimMethod -MethodName ScanForUpdates -Arguments @{SearchCriteria="IsInstalled=0";OnlineScan=$true}            

PS > $result

HResult ReturnValue Updates
------- ----------- -------
      0           0 {MSFT_WUUpdate (UpdateID = "ac3ad46a-f129-4ee7-bd4d-360385e87a1a")
	  
PS > $result.Updates

Description    : The Microsoft .NET Framework 4.7 is a highly compatible, in-place update for all the previous versions
                  of .NET Framework 4.X. After you install this update, you may have to restart your computer.
KBArticleID    :
MsrcSeverity   :
RevisionNumber : 202
Title          : Microsoft .NET Framework 4.7 for Windows 10 Version 1607 and Windows Server 2016 for x64 (KB3186568)
UpdateID       : ac3ad46a-f129-4ee7-bd4d-360385e87a1a
PSComputerName :

Description    : A security issue has been identified in a Microsoft software product that could affect your system. Yo
                 u can help protect your system by installing this update from Microsoft. For a complete listing of the
                  issues that are included in this update, see the associated Microsoft Knowledge Base article. After y
                 ou install this update, you may have to restart your system.
KBArticleID    :
MsrcSeverity   : Moderate
RevisionNumber : 201
Title          : 2017-08 Cumulative Update for Windows Server 2016 for x64-based Systems (KB4034658)
UpdateID       : fbf6de89-bf23-48b9-aef0-aae76f268708
PSComputerName :

Description    : Install this update to revise the definition files that are used to detect viruses, spyware, and other
                  potentially unwanted software. Once you have installed this item, it cannot be removed.
KBArticleID    :
MsrcSeverity   :
RevisionNumber : 200
Title          : Definition Update for Windows Defender - KB2267602 (Definition 1.249.1352.0)
UpdateID       : c9219ede-5e09-4639-a278-9cb27136e751
PSComputerName :
 
# Скачать обновление под индексом 2 - DownloadUpdates            
Invoke-CimMethod -InputObject $ci -MethodName DownloadUpdates -Arguments @{            
 Updates = [CimInstance[]]$result.Updates.Item(2)            
}            
HResult ReturnValue PSComputerName
------- ----------- --------------
      0           0
               
# Установить обновление под индексом 2 - InstallUpdates            
Invoke-CimMethod -InputObject $ci -MethodName InstallUpdates -Arguments @{            
 Updates = [CimInstance[]]$result.Updates.Item(2)            
}            

HResult ReturnValue PSComputerName
------- ----------- --------------
      0           0
# Выборочно скачать обновление (исключим для примера Microsoft .NET Framework 4.7)            
Invoke-CimMethod -InputObject $ci -MethodName DownloadUpdates -Arguments @{            
 Updates = [CimInstance[]]($result.Updates.Where{$_.UpdateID -ne 'ac3ad46a-f129-4ee7-bd4d-360385e87a1a'})            
}            

HResult ReturnValue PSComputerName
------- ----------- --------------
      0           0
               
# Выборочно установить обновление (исключим для примера Microsoft .NET Framework 4.7)            
Invoke-CimMethod -InputObject $ci -MethodName InstallUpdates -Arguments @{            
 Updates = [CimInstance[]]($result.Updates.Where{$_.UpdateID -ne 'ac3ad46a-f129-4ee7-bd4d-360385e87a1a'})            
}            

HResult ReturnValue PSComputerName
------- ----------- --------------
      0           0
 
# Установить все обновления - ApplyApplicableUpdates            
Invoke-CimMethod -InputObject $ci -MethodName ApplyApplicableUpdates            

HResult ReturnValue PSComputerName
------- ----------- --------------
      0           0
 
# Текущий статус операции            
Invoke-CimMethod -InputObject $ci -MethodName CheckWUOperationState            

operationState ReturnValue PSComputerName
-------------- ----------- --------------
Idle                     0

operationState ReturnValue PSComputerName
-------------- ----------- --------------
Downloading              0

operationState ReturnValue PSComputerName
-------------- ----------- --------------
Installing               0
 
# Список установленных обновлений            
$ci = New-CimInstance -Namespace root/Microsoft/Windows/WindowsUpdate -ClassName MSFT_WUOperationsSession            
$result = $ci | Invoke-CimMethod -MethodName ScanForUpdates -Arguments @{SearchCriteria="IsInstalled=1";OnlineScan=$true}            
$result.Updates

Отдельно стоит уточнить про метод UninstallUpdates при вызове данного метода для обновлений, которые устанавливались не через WSUS , данный метод вернет — 2149842984|WU_E_UNINSTALL_NOT_ALLOWED|uninstall is not allowed due to non managed environment .  В модуле PSWindowsUpdate для удаления используется утилита wusa.exe .

# Удалить обновление под индексом 2 - UninstallUpdates            
Invoke-CimMethod -InputObject $ci -MethodName UninstallUpdates -Arguments @{            
 Updates = [CimInstance[]]$result.Updates.Item(2)            
}

Полезные ссылки:

https://docs.microsoft.com/en-us/windows-server/get-started/manage-nano-server

https://blogs.technet.microsoft.com/nanoserver/2016/01/16/updating-nano-server-using-windows-update-or-windows-server-update-service/

https://blogs.technet.microsoft.com/nanoserver/2016/10/07/updating-nano-server/

Read Full Post »