そして、SaaSシステムの長所と短所は、それが私たちによって制御されていないことであり、私たちは(ほとんどの場合)主な機能の更新と新機能の追加のサイクルに影響を与えることはできません。ただし、これらの更新は有益であり、機能に大きな変更がない場合もあれば、インフラストラクチャにとって重要である場合もあります。これにより、ビジネスに追加のリスクが発生するため、ITエンジニアと同様に安心感が得られます。すべてをサポートします。この記事では、追加のアプリケーションをインストールせずに、Microsoft365の更新プログラムに関する必要なメッセージをすべて取得する方法について説明します。必要なのは、Azure Active Directory、Azure Automation、PowerShellのAPIアクセス用の登録済みアプリケーション、およびTelegramのボットです。
仕事:
, API M365, Teams Telegram.
:
Microsoft 365 Roadmap
Microsoft 365 Message Center
, , .. RSS feed, RSS Telegram . .
, Roadmap , , , Microsoft Message Center . , , .
, PowerShell, . . Azure Automation . , Azure Active Directory .
1. Azure Active Directory
2. Manage App registrations
3. New Registration Azure Active Directory
4. Name , .
5. Register . , , :
Application ID
Directory ID
.
6. , Client Secret, . Certificates & Secrets New Client Secret. , Client Secret.
7. Description .
8. Value , , .
9. Message Center. API Permissions
10. Graph API User.Read, .
.
M365 , Delegated Permissions, , Application Permissions . , - , MFA , Application Permissions Global . User.Read , . Remove permission.
Message Center. Add Permission > Office 365 Management API
11. Application Permissions > ServiceHealth.Read Add Permissions
12. Global Admin, Grant admin consent, ,
13. , Granted for <tenant name>
.
, M365 API, Get-APIToken. :
Application ID
Tenant ID (directory ID)
App Secret (Client Secret)
5
Rest URL :
“https://login.microsoftonline.com/” + $TenantID + “/oauth2/v2.0/token”
Function Get-ApiToken {
[CmdletBinding()]
param (
[Parameter(Mandatory=$True)]
[String]
$AppId, $AppSecret, $TenantID
)
$AuthUrl = "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token"
$Scope = "https://manage.office.com/.default"
$Body = @{
client_id = $AppId
client_secret = $AppSecret
scope = $Scope
grant_type = 'client_credentials'
}
$PostSplat = @{
ContentType = 'application/x-www-form-urlencoded'
Method = 'POST'
Body = $Body
Uri = $AuthUrl
}
try {
Invoke-RestMethod @PostSplat -ErrorAction Stop
}
catch {
Write-Warning "$(Get-Date): Exception was caught: $($_.Exception.Message)"
}
}
Token .
try {
$Token = Get-ApiToken -AppId $ClientId -AppSecret $ClientSecret -TenantID $TenantId -ErrorAction Stop
Write-Output "$(Get-Date): Token successfully issued"
}
catch {
Write-Error "$(Get-Date): Can't get the token!"
break
}
:
, Message Center , Get-MCMessages Get-ApiRequestResult
Get-ApiRequestResult.
URL , .
header Splat.
Function Get-ApiRequestResult {
[CmdletBinding()]
param (
[Parameter(Mandatory=$True)]
[String]
$Url, $Method, $Token
)
$Header = @{
Authorization = "$($Token.token_type) $($Token.access_token)"
}
$PostSplat = @{
ContentType = 'application/json'
Method = $Method
Header = $Header
Uri = $Url
}
try {
Invoke-RestMethod @PostSplat -ErrorAction Stop
}
catch {
$Ex = $_.Exception
$ErrorResponse = $ex.Response.GetResponseStream()
$Reader = New-Object System.IO.StreamReader($errorResponse)
$Reader.BaseStream.Position = 0
$Reader.DiscardBufferedData()
$ResponseBody = $Reader.ReadToEnd();
Write-Output "$(Get-Date): Response content:`n$responseBody" -f Red
throw Write-Error "$(Get-Date): Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
}
}
Message Center.
Get https://manage.office.com/api/ServiceComms/Messages
Function Get-MCMessages {
[CmdletBinding()]
param (
[Parameter(Mandatory=$True)]
$APIUrl, $TenantId
)
$ApiVersion = "v1.0"
$MS_resource = "ServiceComms/Messages?&`$filter=MessageType%20eq%20'MessageCenter'"
$Uri = "$APIUrl/$ApiVersion/$($TenantId)/$MS_resource"
$Method = "GET"
try {
Get-ApiRequestResult -Url $Uri -Token $Token -Method $Method -ErrorAction Stop
Write-Output "$(Get-Date): New messages successfully collected"
}
catch {
$Ex = $_.Exception
$ErrorResponse = $ex.Response.GetResponseStream()
$Reader = New-Object System.IO.StreamReader($errorResponse)
$Reader.BaseStream.Position = 0
$Reader.DiscardBufferedData()
$ResponseBody = $Reader.ReadToEnd();
Write-Output "$(Get-Date): Response content:`n$responseBody" -f Red
throw Write-Error "$(Get-Date): Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
}
}
? , API M365 , , , . , $MS_Resource $URL Get-MCMessages. Intune, Get-IntuneManagedDevices, MS_Resource "deviceManagement/managedDevices", URL https://graph.microsoft.com, .
:
, Azure Automation, . , - «» , . LastUpdatedTime, .
Runbook Azure Automation 1 , . , : , . :
$CurrentTime = Get-Date
$ontrolTime = ($CurrentTime).AddMinutes(-60)
Get-MCMessages.
$Messages = Get-MCmessages -APIUrl $APIUrl -TenantId $TenantId
,
$NewMessages = $Messages.value | Where-Object {$(Get-date $($_.LastUpdatedTime)) -ge $controlTime}
$NewMessagesCount = $NewMessages.id.count
if ($NewMessagesCount -gt 0) {
Write-Output "$(Get-Date): There are $NewMessagesCount new messages"
}
else {
Write-Output "$(Get-Date): There is no new messages"
break
}
, , . .
if ($NewMessagesCount -gt 0) {
foreach ($NewMessage in $NewMessages){
}
}
.
$MessagePreview = $NewMessage.Messages.MessageText
$MessageID = $NewMessage.id
$MessageTitle = $NewMessage.Title
$MessageType = $NewMessage.actiontype
$PublishedTime = Get-date $($NewMessage.Messages.publishedTime)
$UpdatedTime = Get-Date $($NewMessage.LastUpdatedTime)
MessageText html, , Telegram . , , , Telegram . Remove-HtmlTags, html , .
. :
- .
- , .
- - .
, , . :
Function Remove-HtmlTags {
param (
$Text
)
$SimpleTags = @(
'p',
'i',
'span',
'div',
'ul',
'ol',
'h1',
'h2',
'h3',
'div'
)
$TagsToRemove = (
"\<\/?font[^>]*\>",
'\<br\s?\/?\>',
'\&rarr',
'style=""',
' target\=\"_blank\"'
)
$TagsToReplace = @(
@('\[','<b>'),
@('\]','</b>'),
@('\<A','<a'),
@('\<\/A\>','</a>'),
@('\<img[^>]*\>','[There was an image]'),
@(' ',' '),
@('\<li\>',' -'),
@('\<\/li\>',"`n")
)
foreach($Tag in $SimpleTags){
$Pattern = "\<\/?$tag\>"
$Text = $Text -replace $Pattern
}
foreach($Tag in $TagsToRemove){
$Text = $Text -replace $Tag
}
foreach($Tag in $TagsToReplace){
$Text = $Text -replace $Tag
}
foreach($Tag in $SimpleTags){
$Pattern = "\<\/?$Tag\>"
$Text = $Text -replace $Pattern
}
$Text
}
, , , , , - . - , , , .
, . , , Microsoft , . </p>, , , html . .
$MessageTextWithHtmlString = $MessagePreview -split ('\<\/p\>')
$FormattedMesssageText = $(Remove-HtmlTags $MessageTextWithHtmlString) -creplace '(?m)^\s*\r?\n',''
. Title .
$PublishingInfo = "Published: $PublishedTime `nUpdated: $UpdatedTime"
$TgmMessage = "$BoldMessageTitle `n$MessageDescription `n$PublishingInfo `n$FormattedMesssageText"
Microsoft , , . .
$MessageActionRequiredByDate = $NewMessage.ActionRequiredByDate
$MessageAdditionalInformation = $NewMessage.ExternalLink
$MessageBlogLink = $NewMessage.BlogLink
if($MessageActionRequiredByDate){
$TgmMessage += "`nAction required by date: $MessageActionRequiredByDate"
}
elseif ($MessageAdditionalInformation) {
$TgmMessage += "`n$MessageAdditionalInformation'>Additional info"
}
elseif ($MessageBlogLink) {
$TgmMessage += "`n$MessageBlogLink'>Blog"
}
. , .
ChatID, Token, ParsingType, - , .
function Send-TelegramMessage {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]
$MessageText,$TokenTelegram,$ChatID
[Parameter(Mandatory=$true)]
[ValidateSet("html","markdown")]
[string]$ParsingType
)
$URL_set = "https://api.telegram.org/bot$TokenTelegram/sendMessage"
$Body = @{
text = $MessageText
parse_mode = $ParsingType
chat_id = $chatID
}
$MessageJson = $body | ConvertTo-Json
try {
Invoke-RestMethod $URL_set -Method Post -ContentType 'application/json; charset=utf-8' -Body $MessageJson -ErrorAction Stop
Write-Output "$(Get-Date): Message has been sent"
}
catch {
Write-Error "$(Get-Date): Can't sent message"
Write-Output "$(Get-Date): StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Output "$(Get-Date): StatusDescription:" $_.Exception.Response.StatusDescription
throw
}
}
, , :
Send-TelegramMessage -MessageText $TgmMessage -TokenTelegram $TokenTelegram -ChatID $chatID -ParsingType 'html'
:
, ID, , . Azure Automation Secure Assets. .
PSボットを改善するための貢献者と提案に喜んでいます。