В заметке пример скрипта, который отправляет пользователям инструкцию по смене пароля по электронной почте за 5 дней до срока окончания действия пароля.
Область действия: Вся организация
Классификация
Ресурсная оценка
Качественная оценка |
Количественная оценка |
Итоговая оценка | ||||
---|---|---|---|---|---|---|
Стоимость |
Трудозатраты |
Сложность |
Стоимость, тыс. руб |
Трудозатраты, дней/ год |
||
CAPEX ? |
Неизвестно
|
Неизвестно
|
Неизвестно
|
Неизвестно
|
Неизвестно
|
Отсутствует
|
OPEX ? |
Неизвестно
|
Неизвестно
|
Неизвестно
|
Неизвестно
|
Неизвестно
|
Связанные риски
Мы используем cookie-файлы, чтобы получить статистику, которая помогает нам улучшить сервис для вас с целью персонализации сервисов и предложений. Вы может прочитать подробнее о cookie-файлах или изменить настройки браузера. Продолжая пользоваться сайтом, вы даёте согласие на использование ваших cookie-файлов и соглашаетесь с Политикой обработки персональных данных.
Заметки
3Скрипт уведомления о заканчивающемся пароле
В письме применяются встроенные (inline) изображения;
# PowerShell $Error.clear() $elevel = 0 $mailto=@('infosec@mycorp.local') Function Log($str) { Write-Output "$(Get-Date -Format 'dd.MM.yy HH:mm:ss') -> $str" } Function Ending([int]$d, [string[]]$ends = ('ок','ка','ки')) { $y = $d % 10 If ($d -ge 10 -and [int]($d / 10 % 10) -eq 1) {$ends[0]} ElseIf ($y -eq 1) {$ends[1]} ElseIf ((2,3,4) -eq $y) {$ends[2]} Else {$ends[0]} } . "$PSScriptRoot\Send-MailMessage.ps1" # Вспомогательный скрипт для отправки электронной почты $now = Get-Date $nowplus = $now.AddDays(5) $workdir = "$PSScriptRoot\work" $usersdir = "$workdir\SamAccountName" $workdir,$usersdir | ? {-not (Test-Path -LiteralPath $_ -Type Container)} | % { try { New-Item -Path $_ -ItemType Directory -Force -ErrorAction Stop | Out-Null } catch { Log "Cannot create workdir `"$_`"" $elevel = 1 } } If ($elevel -eq 0) { $EmailToUsr = @{ To = $mailto Bcc = 'infosec@mycorp.ru' From = 'Отдел информационной безопасности <infosec@mycorp.ru>' Subject = 'Срок действия Вашего пароля скоро закончится' BodyAsHtml = $true SMTPServer = 'mail' Priority = 'High' InlineAttachments = @{ img01 = "$PSScriptRoot\html\ctrl+alt+del.png" img02 = "$PSScriptRoot\html\change1.png" img03 = "$PSScriptRoot\html\change2.png" } } if ($debug) {$EmailToUsr.Remove('Bcc')} $EmailToUsrTemplate = "$PSScriptRoot\html\EmailToUsr.html" $EmailTemplate = If (Test-Path -LiteralPath $EmailToUsrTemplate -Type Leaf) {Get-Content -LiteralPath $EmailToUsrTemplate} Else {$null} $excludeFile = "$PSScriptRoot\exclude.txt" $exclude = If (Test-Path -LiteralPath $excludeFile -Type Leaf) {Get-Content -LiteralPath $excludeFile | % {$_.Trim()} | ? {$_ -and (-not $_.StartsWith("#"))}} Else {$null} $sentall = @() $usersall = @() Get-ADUser -Filter {Enabled -eq $true -and PasswordNeverExpires -eq $false} -Properties ObjectGUID,SamAccountName,UserPrincipalName,DisplayName,mail,msDS-UserPasswordExpiryTimeComputed | ` ? {$exclude -notcontains $_.SamAccountName -and $exclude -notcontains $_.DisplayName -and $_.'msDS-UserPasswordExpiryTimeComputed' -ge $now.ToFileTime() -and $_.'msDS-UserPasswordExpiryTimeComputed' -le $nowplus.ToFileTime()} | ` Select-Object -Property ObjectGUID,SamAccountName,UserPrincipalName,DisplayName,mail,@{Name='Expiry'; Expression={[datetime]::FromFileTime($_.'msDS-UserPasswordExpiryTimeComputed')}} | % { $sentall+= "$($_.ObjectGUID)_$(Get-Date $_.Expiry -Format 'yyyyMMdd').txt" $sentfile = "$workdir\$($sentall[-1])" $usersall+= "$($_.SamAccountName).txt" $userfile = "$usersdir\$($usersall[-1])" $days = ($_.Expiry-$now).Days If ($days -eq 0) {$dtxt = 'сегодня'} ElseIf ($days -eq 1) {$dtxt = 'завтра'} Else {$dtxt = "через $days $(Ending $days @('дней','день','дня'))"} try { Set-Content -Value "Пароль истекает $($dtxt)" -LiteralPath $userfile -Encoding UTF8 -Force $Acl = Get-Acl -LiteralPath $userfile $Ar = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $_.UserPrincipalName, 'Read,Delete', 'Allow' $Acl.SetAccessRule($Ar) Set-Acl -LiteralPath $userfile -AclObject $Acl } catch { Log "[err] Error write `"$userfile`" file" $elevel = 1 If (Test-Path -LiteralPath $userfile -Type Leaf) {Remove-Item -LiteralPath $userfile -Force} } If (-not (Test-Path -LiteralPath $sentfile -Type Leaf)) { If (-not $debug -and [bool]($_.mail -as [Net.Mail.MailAddress])) {$EmailToUsr.To = "$($_.DisplayName) <$($_.mail)>"} $EmailToUsr.Body = ($EmailTemplate.replace('<!--LOGIN-->', $_.SamAccountName).replace('<!--NAME-->', $_.DisplayName).replace('<!--DAYS-->', $dtxt) | Out-String) try { Send-MailMessage @EmailToUsr -ErrorAction Stop Set-Content -Value $_.Expiry -LiteralPath $sentfile -Encoding UTF8 -Force Log "Mail sent to $($EmailToUsr.To)" } catch { Log "[err] Error sending mail to $($EmailToUsr.To)" $elevel = 1 } } Else { Log "[inf] Alert already sent to $($_.DisplayName) <$($_.mail)>" } } If ($sentall) {Remove-Item -Path "$workdir\*.txt" -Exclude $sentall -Force} If ($usersall) {Remove-Item -Path "$usersdir\*.txt" -Exclude $usersall -Force} } Log 'Done.' If ($Error) { $elevel = 1 $Error } exit $elevel
Для просмотра файла необходимо авторизоваться!
Скрипт для отправки писем
# PowerShell #requires -Version 2.0 function Send-MailMessage { [CmdletBinding()] param( [Parameter(ValueFromPipeline=$true)] [Alias('PsPath')] [ValidateNotNullOrEmpty()] [string[]] ${Attachments}, [ValidateNotNullOrEmpty()] [Collections.HashTable] ${InlineAttachments}, [ValidateNotNullOrEmpty()] [Net.Mail.MailAddress[]] ${Bcc}, [Parameter(Position=2)] [ValidateNotNullOrEmpty()] [string] ${Body}, [Alias('BAH')] [switch] ${BodyAsHtml}, [ValidateNotNullOrEmpty()] [Net.Mail.MailAddress[]] ${Cc}, [Alias('DNO')] [ValidateNotNullOrEmpty()] [Net.Mail.DeliveryNotificationOptions] ${DeliveryNotificationOption}, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [Net.Mail.MailAddress] ${From}, [Parameter(Mandatory = $true, Position = 3)] [Alias('ComputerName')] [string] ${SmtpServer}, [ValidateNotNullOrEmpty()] [Net.Mail.MailPriority] ${Priority}, [Parameter(Mandatory=$true, Position=1)] [Alias('sub')] [ValidateNotNullOrEmpty()] [string] ${Subject}, [Parameter(Mandatory=$true, Position=0)] [Net.Mail.MailAddress[]] ${To}, [ValidateNotNullOrEmpty()] [Management.Automation.PSCredential] ${Credential}, [switch] ${UseSsl}, [ValidateRange(0, 2147483647)] [int] ${Port} = 25 ) begin { function FileNameToContentType { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $FileName ) $mimeMappings = @{ '.png' = 'image/png' } $extension = [System.IO.Path]::GetExtension($FileName) $contentType = $mimeMappings[$extension] if ([string]::IsNullOrEmpty($contentType)) { return New-Object System.Net.Mime.ContentType } else { return New-Object System.Net.Mime.ContentType($contentType) } } try { $_smtpClient = New-Object Net.Mail.SmtpClient $_smtpClient.Host = $SmtpServer $_smtpClient.Port = $Port $_smtpClient.EnableSsl = $UseSsl if ($null -ne $Credential) { # In PowerShell 2.0, assigning the results of GetNetworkCredential() to the SMTP client sometimes fails (with gmail, in testing), but # building a new NetworkCredential object containing only the UserName and Password works okay. $_tempCred = $Credential.GetNetworkCredential() $_smtpClient.Credentials = New-Object Net.NetworkCredential($Credential.UserName, $_tempCred.Password) } else { $_smtpClient.UseDefaultCredentials = $true } $_message = New-Object Net.Mail.MailMessage $_message.From = $From $_message.Subject = $Subject $Encode = [Text.Encoding]::GetEncoding("UTF-8"); if ($BodyAsHtml) { # $_bodyPart = [Net.Mail.AlternateView]::CreateAlternateViewFromString($Body, 'text/html') $_bodyPart = [Net.Mail.AlternateView]::CreateAlternateViewFromString($Body, $encode, 'text/html') } else { # $_bodyPart = [Net.Mail.AlternateView]::CreateAlternateViewFromString($Body, 'text/plain') $_bodyPart = [Net.Mail.AlternateView]::CreateAlternateViewFromString($Body, $encode, 'text/plain') } $_message.AlternateViews.Add($_bodyPart) if ($PSBoundParameters.ContainsKey('DeliveryNotificationOption')) { $_message.DeliveryNotificationOptions = $DeliveryNotificationOption } if ($PSBoundParameters.ContainsKey('Priority')) { $_message.Priority = $Priority } foreach ($_address in $To) { if (-not $_message.To.Contains($_address)) { $_message.To.Add($_address) } } if ($null -ne $Cc) { foreach ($_address in $Cc) { if (-not $_message.CC.Contains($_address)) { $_message.CC.Add($_address) } } } if ($null -ne $Bcc) { foreach ($_address in $Bcc) { if (-not $_message.Bcc.Contains($_address)) { $_message.Bcc.Add($_address) } } } } catch { $_message.Dispose() throw } if ($PSBoundParameters.ContainsKey('InlineAttachments')) { foreach ($_entry in $InlineAttachments.GetEnumerator()) { $_file = $_entry.Value.ToString() if ([string]::IsNullOrEmpty($_file)) { $_message.Dispose() throw "Send-MailMessage: Values in the InlineAttachments table cannot be null." } try { $_contentType = FileNameToContentType -FileName $_file $_attachment = New-Object Net.Mail.LinkedResource($_file, $_contentType) $_attachment.ContentId = $_entry.Key $_bodyPart.LinkedResources.Add($_attachment) } catch { $_message.Dispose() throw } } } } process { if ($null -ne $Attachments) { foreach ($_file in $Attachments) { try { $_contentType = FileNameToContentType -FileName $_file $_message.Attachments.Add((New-Object Net.Mail.Attachment($_file, $_contentType))) } catch { $_message.Dispose() throw } } } } end { try { $_smtpClient.Send($_message) } catch { throw } finally { $_message.Dispose() } } } # function Send-MailMessage
Для просмотра файла необходимо авторизоваться!