업데이트 관리 로그 쿼리

업데이트 관리 배포 중에 제공되는 세부 정보 외에도 Log Analytics 작업 영역에 저장된 로그를 검색할 수 있습니다. Automation 계정에서 로그를 검색하려면 업데이트 관리를 선택하고 배포와 연결된 Log Analytics 작업 영역을 엽니다.

로그 쿼리를 사용자 지정하거나 다른 클라이언트에서 사용할 수도 있습니다. Log Analytics 검색 API 설명서를 참조하세요.

업데이트 레코드 쿼리

업데이트 관리는 Windows 및 Linux VM에 대한 레코드 및 로그 검색 결과에 표시되는 데이터 형식을 수집합니다. 다음 섹션에서는 이러한 레코드에 대해 설명합니다.

쿼리 업데이트 레코드

사용 가능한 업데이트와 컴퓨터에 대한 설치 상태 나타내는 형식의 Update 레코드가 만들어집니다. 이러한 레코드는 다음 표의 속성을 가집니다.

속성 설명
TenantId 조직의 Microsoft Entra ID 인스턴스를 나타내는 고유 식별자입니다.
SourceSystem 레코드의 원본 시스템입니다. 값이 OperationsManager입니다.
TimeGenerated 레코드 생성 날짜와 시간입니다.
SourceComputerId 원본 컴퓨터를 나타내는 고유 식별자입니다.
타이틀 업데이트의 제목입니다.
분류 승인 분류. 값이 업데이트.
PublishedDate(UTC) 업데이트를 Windows Update에서 다운로드하여 설치할 준비가 된 날짜입니다.
컴퓨터 보고 컴퓨터의 정규화된 do기본 이름입니다.
UpdateState 업데이트의 현재 상태입니다.
Product 업데이트가 적용되는 제품입니다.
OSType 운영 체제의 유형입니다. 값은 Windows 또는 Linux입니다.
productVersion 업데이트의 버전입니다.
제품 아치 적용 가능한 컴퓨터 아키텍처
CVENumbers 일반적인 취약성 및 노출 수
BulletinUrl 공지의 URL
BulletinID 공지 ID 번호입니다.
PackageRepository 패키지의 리포지토리 정보입니다.
PackageSeverity 업데이트의 심각도입니다.
OSName 운영 체제의 유형입니다. 값은 Windows 또는 Linux입니다.
OSVersion 운영 체제의 버전입니다.
OSFullName 운영 체제의 이름입니다.
SubscriptionId Azure 구독에 대한 고유 식별자입니다.
ResourceGroup 리소스가 속한 리소스 그룹의 이름입니다.
ResourceProvider 리소스 공급자입니다.
리소스 리소스의 이름입니다.
ResourceId 레코드와 연결된 리소스에 대한 고유 식별자입니다.
ResourceType 리소스 유형.
ComputerEnvironment 환경. 가능한 값은 Azure 또는 비 Azure입니다.
VMUUID 가상 머신의 고유 식별자입니다.
MG 관리 그룹 또는 Log Analytics 작업 영역에 대한 고유 식별자입니다.
ManagementGroupName Operations Manager 관리 그룹 또는 Log Analytics 작업 영역의 이름입니다.
MSRCSeverity 취약성에 대한 심각도입니다. 값:
위험
중요
보통
낮음
KBID Windows 업데이트에 대한 기술 자료 문서 ID입니다.
UpdateID 소프트웨어 업데이트의 고유 식별자입니다.
RevisionNumber 업데이트의 특정 수정 버전에 대한 수정 번호입니다.
선택 사항 레코드가 선택적이면 True이고, 그렇지 않으면 False입니다.
RebootBehavior 업데이트를 설치/제거한 후의 다시 부팅 동작입니다.
MSRCBulletinID 보안 공지 ID 번호입니다.
승인됨 레코드가 승인되면 True이고, 그렇지 않으면 False입니다.
ApprovalSource Windows 운영 체제에만 적용됩니다. 레코드의 승인 원본입니다. 값은 Microsoft Update입니다.
InstallTimePredictionSeconds
InstallTimeDeviationRangeSeconds
InstallTimeAvailable
Type 레코드 종류. 값은 Update입니다.

업데이트 배포 상태 레코드 쿼리

컴퓨터에서 예약된 배포의 UpdateRunProgress 업데이트 배포 상태 제공하는 형식의 레코드가 만들어집니다. 이러한 레코드는 다음 표의 속성을 가집니다.

속성 설명
TenantId 조직의 Microsoft Entra ID 인스턴스를 나타내는 고유 식별자입니다.
SourceSystem 레코드의 원본 시스템입니다. 값이 OperationsManager입니다.
TimeGenerated 레코드 생성 날짜와 시간입니다.
MG 관리 그룹 또는 Log Analytics 작업 영역에 대한 고유 식별자입니다.
ManagementGroupName Operations Manager 관리 그룹 또는 Log Analytics 작업 영역의 이름입니다.
SourceComputerId 원본 컴퓨터를 나타내는 고유 식별자입니다.
KBID Windows 업데이트에 대한 기술 자료 문서 ID입니다.
UpdateId 소프트웨어 업데이트의 고유 식별자입니다.
SucceededOnRetry 첫 번째 시도에서 업데이트 실행이 실패하고 현재 작업이 재시도 시도인지 여부를 나타내는 값입니다.
ErrorResult Windows 업데이트 업데이트가 설치되지 않으면 생성된 오류 코드입니다.
UpdateRunName 업데이트 일정의 이름입니다.
InstallationStatus 클라이언트 컴퓨터의 가능한 업데이트 설치 상태입니다.
NotStarted - 작업이 아직 트리거되지 않았습니다.
Failed - 작업이 시작되었지만 예외로 실패했습니다.
InProgress - 작업이 진행 중입니다.
MaintenanceWindowExceeded - 실행이 남아 있지만 유지 관리 기간 간격에 도달한 경우입니다.
Succeeded - 작업이 성공했습니다.
Install Failed - 업데이트를 설치하지 못했습니다.
NotIncluded - 해당 업데이트의 분류가 입력 분류 목록의 고객 항목과 일치하지 않습니다.
Excluded - 사용자가 제외된 목록에 KBID를 입력합니다. 패치하는 동안 제외된 목록의 KBID가 시스템에서 검색된 업데이트 KB ID와 일치하는 경우 제외된 것으로 표시됩니다.
컴퓨터 보고 컴퓨터의 정규화된 do기본 이름입니다.
타이틀 업데이트의 제목입니다.
Product 업데이트가 적용되는 제품입니다.
OSType 운영 체제의 유형입니다. 값은 Windows 또는 Linux입니다.
StartTime (UTC) 업데이트가 설치되도록 예약된 시간입니다. 이 속성은 현재 사용되지 않습니다. TimeGenerated를 참조하세요.
EndTime(UTC) 동기화 프로세스가 종료된 시간입니다. 이 속성은 현재 사용되지 않습니다. TimeGenerated를 참조하세요.
CorrelationId 업데이트에 대해 실행되는 Runbook 작업의 고유 식별자입니다.
SubscriptionId Azure 구독에 대한 고유 식별자입니다.
ResourceGroup 리소스가 속한 리소스 그룹의 이름입니다.
ResourceProvider 리소스 공급자입니다.
리소스 리소스의 이름입니다.
ResourceId 레코드와 연결된 리소스에 대한 고유 식별자입니다.
ResourceType 리소스 종류.
ComputerEnvironment 환경. 값은 Azure 또는 Non-Azure입니다.
VMUUID 가상 머신의 고유 식별자입니다.
Type 업데이트 유형. 값이 UpdateRunProgress입니다.
_ResourceId 레코드와 연결된 리소스에 대한 고유 식별자입니다.

쿼리 업데이트 요약 레코드

컴퓨터에서 업데이트 요약을 제공하는 형식의 UpdateSummary 레코드가 만들어집니다. 이러한 레코드는 다음 표의 속성을 가집니다.

속성 설명
TenantId 조직의 Microsoft Entra ID 인스턴스를 나타내는 고유 식별자입니다.
SourceSystem 레코드의 원본 시스템입니다. 값이 OpsManager입니다.
TimeGenerated 레코드 생성 날짜와 시간입니다.
MG 관리 그룹 또는 Log Analytics 작업 영역에 대한 고유 식별자입니다.
ManagementGroupName Operations Manager 관리 그룹 또는 Log Analytics 작업 영역의 이름입니다.
SourceComputerId 가상 머신의 고유 식별자입니다.
LastUpdateApplied(UTC)
OldestMissingSecurityUpdateInDays 설치되지 않은 것으로 검색된 적용 가능한 가장 오래된 업데이트의 총 일수입니다.
OldestMissingSecurityUpdateBucket 누락된 가장 오래된 보안 버킷의 지정자입니다. 값:
최근 값이 30일 미만인 경우
30일 전
60일 전
90일 전
120일 전
150일 전
180일 전
값이 180일보다 큰 경우 이전 버전입니다.
WindowsUpdateSetting Windows 업데이트 에이전트의 상태입니다. 가능한 값은 다음과 같습니다.
Scheduled installation
Notify before installation
Error returned from unhealthy WUA agent
WindowsUpdateAgentVersion Windows Update 에이전트의 버전입니다.
WSUSServer Windows Update 에이전트에 문제가 있는 경우 문제 해결을 지원합니다.
컴퓨터 보고 컴퓨터의 정규화된 do기본 이름입니다.
OsVersion 운영 체제의 버전입니다.
NETRuntimeVersion Windows 컴퓨터에 설치된 .NET Framework 버전입니다.
위험업데이트미사일 누락된 적용 가능한 중요 업데이트의 수입니다.
보안업데이트미사용 적용 가능한 누락된 보안 업데이트 수입니다.
기타업데이트미사일 검색된 누락 업데이트의 수입니다.
Total업데이트Missing 적용 가능한 누락된 업데이트의 총 수입니다.
RestartPending 다시 시작이 보류 중인 경우 True이고, 그렇지 않으면 False입니다.
SubscriptionId Azure 구독에 대한 고유 식별자입니다.
ResourceGroup 리소스를 포함하는 리소스 그룹의 이름입니다.
ResourceProvider 리소스 공급자입니다.
리소스 레코드에 대한 리소스의 이름입니다.
ResourceId 레코드와 연결된 리소스에 대한 고유 식별자입니다.
ResourceType 리소스 종류.
ComputerEnvironment 환경. 값은 Azure 또는 Non-Azure입니다.
VMUUID 가상 머신의 고유 식별자입니다.
Type 레코드 종류. 값이 UpdateSummary입니다.
_ResourceId 레코드와 연결된 리소스에 대한 고유 식별자입니다.

샘플 쿼리

다음 섹션에서는 업데이트 관리를 위해 수집되는 업데이트 레코드에 대한 샘플 로그 쿼리를 제공합니다.

비 Azure 컴퓨터가 업데이트 관리에 사용하도록 설정되어 있는지 확인

직접 연결된 컴퓨터가 Azure Monitor 로그와 통신하는지 확인하려면 다음 로그 검색 중 하나를 실행합니다.

Linux

Heartbeat
| where OSType == "Linux" | summarize arg_max(TimeGenerated, *) by SourceComputerId | top 500000 by Computer asc | render table

Windows

Heartbeat
| where OSType == "Windows" | summarize arg_max(TimeGenerated, *) by SourceComputerId | top 500000 by Computer asc | render table

Windows 컴퓨터에서 다음 정보를 검토하여 Azure Monitor 로그를 사용하여 에이전트 연결을 확인할 수 있습니다.

  1. 제어판 Microsoft Monitoring Agent를 엽니다. Azure Log Analytics 탭에서 에이전트는 다음 메시지를 표시합니다. Microsoft Monitoring Agent가 Log Analytics에 성공적으로 연결되었습니다.

  2. Windows 이벤트 로그를 엽니다. Application and Services Logs\Operations Manager로 이동하여 원본 서비스 커넥트or에서 이벤트 ID 3000 및 이벤트 ID 5002를 검색합니다. 이러한 이벤트는 컴퓨터가 Log Analytics 작업 영역에 등록되었으며 구성을 수신하고 있음을 나타냅니다.

에이전트가 Azure Monitor 로그와 통신할 수 없고 에이전트가 방화벽 또는 프록시 서버를 통해 인터넷과 통신하도록 구성된 경우 방화벽 또는 프록시 서버가 제대로 구성되었는지 확인합니다. 방화벽 또는 프록시 서버가 올바르게 구성되어 있는지 확인하는 방법을 알아보려면 Windows 에이전트에 대한 네트워크 구성 또는 Linux 에이전트에 대한 네트워크 구성을 참조하세요.

참고 항목

Linux 시스템이 프록시 또는 Log Analytics 게이트웨이와 통신하도록 구성되어 있고 업데이트 관리를 사용하도록 설정하는 경우 다음 명령을 사용하여 파일에 대한 omiuser 그룹 읽기 권한을 부여하도록 권한을 업데이트 proxy.conf 합니다.

sudo chown omsagent:omiusers /etc/opt/microsoft/omsagent/proxy.conf sudo chmod 644 /etc/opt/microsoft/omsagent/proxy.conf

새로 추가된 Linux 에이전트는 평가가 수행된 후 업데이트상태 표시합니다. 이 프로세스는 최대 6시간이 걸릴 수 있습니다.

Operations Manager 관리 그룹이 Azure Monitor 로그와 통신하는지 확인하려면 Azure Monitor 로그와 Operations Manager 통합 유효성 검사를 참조하세요.

단일 Azure VM 평가 쿼리(Windows)

VMUUID 값을 쿼리 중인 가상 머신의 VM GUID로 바꿉니다. Azure Monitor 로그에서 다음 쿼리를 실행하여 사용해야 하는 VMUUID를 찾을 수 있습니다. Update | where Computer == "<machine name>" | summarize by Computer, VMUUID

누락 업데이트 요약

Update
| where TimeGenerated>ago(14h) and OSType!="Linux" and (Optional==false or Classification has "Critical" or Classification has "Security") and VMUUID=~"b08d5afa-1471-4b52-bd95-a44fea6e4ca8"
| summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification, Approved) by Computer, SourceComputerId, UpdateID
| where UpdateState=~"Needed" and Approved!=false
| summarize by UpdateID, Classification
| summarize allUpdatesCount=count(), criticalUpdatesCount=countif(Classification has "Critical"), securityUpdatesCount=countif(Classification has "Security"), otherUpdatesCount=countif(Classification !has "Critical" and Classification !has "Security")

누락된 업데이트 목록

Update
| where TimeGenerated>ago(14h) and OSType!="Linux" and (Optional==false or Classification has "Critical" or Classification has "Security") and VMUUID=~"8bf1ccc6-b6d3-4a0b-a643-23f346dfdf82"
| summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification, Title, KBID, PublishedDate, Approved) by Computer, SourceComputerId, UpdateID
| where UpdateState=~"Needed" and Approved!=false
| project-away UpdateState, Approved, TimeGenerated
| summarize computersCount=dcount(SourceComputerId, 2), displayName=any(Title), publishedDate=min(PublishedDate), ClassificationWeight=max(iff(Classification has "Critical", 4, iff(Classification has "Security", 2, 1))) by id=strcat(UpdateID, "_", KBID), classification=Classification, InformationId=strcat("KB", KBID), InformationUrl=iff(isnotempty(KBID), strcat("https://support.microsoft.com/kb/", KBID), ""), osType=2
| sort by ClassificationWeight desc, computersCount desc, displayName asc
| extend informationLink=(iff(isnotempty(InformationId) and isnotempty(InformationUrl), toobject(strcat('{ "uri": "', InformationUrl, '", "text": "', InformationId, '", "target": "blank" }')), toobject('')))
| project-away ClassificationWeight, InformationId, InformationUrl

단일 Azure VM 평가 쿼리(Linux)

일부 Linux 배포판의 경우 Azure Resource Manager 및 Azure Monitor 로그에 저장된 VMUUID 값과 엔디언이 일치하지 않습니다. 다음 쿼리는 엔디언의 일치 여부를 확인합니다. VMUUID 값을 GUID의 big-endian 및 little-endian 형식으로 바꿔서 결과를 제대로 반환합니다. Azure Monitor 로그에서 다음 쿼리를 실행하여 사용해야 하는 VMUUID를 찾을 수 있습니다. Update | where Computer == "<machine name>" | summarize by Computer, VMUUID

누락 업데이트 요약

Update
| where TimeGenerated>ago(5h) and OSType=="Linux" and (VMUUID=~"625686a0-6d08-4810-aae9-a089e68d4911" or VMUUID=~"a0865662-086d-1048-aae9-a089e68d4911")
| summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification) by Computer, SourceComputerId, Product, ProductArch
| where UpdateState=~"Needed"
| summarize by Product, ProductArch, Classification
| summarize allUpdatesCount=count(), criticalUpdatesCount=countif(Classification has "Critical"), securityUpdatesCount=countif(Classification has "Security"), otherUpdatesCount=countif(Classification !has "Critical" and Classification !has "Security")

누락된 업데이트 목록

Update
| where TimeGenerated>ago(5h) and OSType=="Linux" and (VMUUID=~"625686a0-6d08-4810-aae9-a089e68d4911" or VMUUID=~"a0865662-086d-1048-aae9-a089e68d4911")
| summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification, BulletinUrl, BulletinID) by Computer, SourceComputerId, Product, ProductArch
| where UpdateState=~"Needed"
| project-away UpdateState, TimeGenerated
| summarize computersCount=dcount(SourceComputerId, 2), ClassificationWeight=max(iff(Classification has "Critical", 4, iff(Classification has "Security", 2, 1))) by id=strcat(Product, "_", ProductArch), displayName=Product, productArch=ProductArch, classification=Classification, InformationId=BulletinID, InformationUrl=tostring(split(BulletinUrl, ";", 0)[0]), osType=1
| sort by ClassificationWeight desc, computersCount desc, displayName asc
| extend informationLink=(iff(isnotempty(InformationId) and isnotempty(InformationUrl), toobject(strcat('{ "uri": "', InformationUrl, '", "text": "', InformationId, '", "target": "blank" }')), toobject('')))
| project-away ClassificationWeight, InformationId, InformationUrl

다중 VM 평가 쿼리

컴퓨터 요약

Heartbeat
| where TimeGenerated>ago(12h) and OSType=~"Windows" and notempty(Computer)
| summarize arg_max(TimeGenerated, Solutions) by SourceComputerId
| where Solutions has "updates"
| distinct SourceComputerId
| join kind=leftouter
(
    Update
    | where TimeGenerated>ago(14h) and OSType!="Linux"
    | summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Approved, Optional, Classification) by SourceComputerId, UpdateID
    | distinct SourceComputerId, Classification, UpdateState, Approved, Optional
    | summarize WorstMissingUpdateSeverity=max(iff(UpdateState=~"Needed" and (Optional==false or Classification has "Critical" or Classification has "Security") and Approved!=false, iff(Classification has "Critical", 4, iff(Classification has "Security", 2, 1)), 0)) by SourceComputerId
)
on SourceComputerId
| extend WorstMissingUpdateSeverity=coalesce(WorstMissingUpdateSeverity, -1)
| summarize computersBySeverity=count() by WorstMissingUpdateSeverity
| union (Heartbeat
| where TimeGenerated>ago(12h) and OSType=="Linux" and notempty(Computer)
| summarize arg_max(TimeGenerated, Solutions) by SourceComputerId
| where Solutions has "updates"
| distinct SourceComputerId
| join kind=leftouter
(
    Update
    | where TimeGenerated>ago(5h) and OSType=="Linux"
    | summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification) by SourceComputerId, Product, ProductArch
    | distinct SourceComputerId, Classification, UpdateState
    | summarize WorstMissingUpdateSeverity=max(iff(UpdateState=~"Needed", iff(Classification has "Critical", 4, iff(Classification has "Security", 2, 1)), 0)) by SourceComputerId
)
on SourceComputerId
| extend WorstMissingUpdateSeverity=coalesce(WorstMissingUpdateSeverity, -1)
| summarize computersBySeverity=count() by WorstMissingUpdateSeverity)
| summarize assessedComputersCount=sumif(computersBySeverity, WorstMissingUpdateSeverity>-1), notAssessedComputersCount=sumif(computersBySeverity, WorstMissingUpdateSeverity==-1), computersNeedCriticalUpdatesCount=sumif(computersBySeverity, WorstMissingUpdateSeverity==4), computersNeedSecurityUpdatesCount=sumif(computersBySeverity, WorstMissingUpdateSeverity==2), computersNeedOtherUpdatesCount=sumif(computersBySeverity, WorstMissingUpdateSeverity==1), upToDateComputersCount=sumif(computersBySeverity, WorstMissingUpdateSeverity==0)
| summarize assessedComputersCount=sum(assessedComputersCount), computersNeedCriticalUpdatesCount=sum(computersNeedCriticalUpdatesCount),  computersNeedSecurityUpdatesCount=sum(computersNeedSecurityUpdatesCount), computersNeedOtherUpdatesCount=sum(computersNeedOtherUpdatesCount), upToDateComputersCount=sum(upToDateComputersCount), notAssessedComputersCount=sum(notAssessedComputersCount)
| extend allComputersCount=assessedComputersCount+notAssessedComputersCount

누락 업데이트 요약

Update
| where TimeGenerated>ago(5h) and OSType=="Linux" and SourceComputerId in ((Heartbeat
| where TimeGenerated>ago(12h) and OSType=="Linux" and notempty(Computer)
| summarize arg_max(TimeGenerated, Solutions) by SourceComputerId
| where Solutions has "updates"
| distinct SourceComputerId))
| summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification) by Computer, SourceComputerId, Product, ProductArch
| where UpdateState=~"Needed"
| summarize by Product, ProductArch, Classification
| union (Update
| where TimeGenerated>ago(14h) and OSType!="Linux" and (Optional==false or Classification has "Critical" or Classification has "Security") and SourceComputerId in ((Heartbeat
| where TimeGenerated>ago(12h) and OSType=~"Windows" and notempty(Computer)
| summarize arg_max(TimeGenerated, Solutions) by SourceComputerId
| where Solutions has "updates"
| distinct SourceComputerId))
| summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification, Approved) by Computer, SourceComputerId, UpdateID
| where UpdateState=~"Needed" and Approved!=false
| summarize by UpdateID, Classification )
| summarize allUpdatesCount=count(), criticalUpdatesCount=countif(Classification has "Critical"), securityUpdatesCount=countif(Classification has "Security"), otherUpdatesCount=countif(Classification !has "Critical" and Classification !has "Security")

컴퓨터 목록

Heartbeat
| where TimeGenerated>ago(12h) and OSType=="Linux" and notempty(Computer)
| summarize arg_max(TimeGenerated, Solutions, Computer, ResourceId, ComputerEnvironment, VMUUID) by SourceComputerId
| where Solutions has "updates"
| extend vmuuId=VMUUID, azureResourceId=ResourceId, osType=1, environment=iff(ComputerEnvironment=~"Azure", 1, 2), scopedToUpdatesSolution=true, lastUpdateAgentSeenTime=""
| join kind=leftouter
(
    Update
    | where TimeGenerated>ago(5h) and OSType=="Linux" and SourceComputerId in ((Heartbeat
    | where TimeGenerated>ago(12h) and OSType=="Linux" and notempty(Computer)
    | summarize arg_max(TimeGenerated, Solutions) by SourceComputerId
    | where Solutions has "updates"
    | distinct SourceComputerId))
    | summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification, Product, Computer, ComputerEnvironment) by SourceComputerId, Product, ProductArch
    | summarize Computer=any(Computer), ComputerEnvironment=any(ComputerEnvironment), missingCriticalUpdatesCount=countif(Classification has "Critical" and UpdateState=~"Needed"), missingSecurityUpdatesCount=countif(Classification has "Security" and UpdateState=~"Needed"), missingOtherUpdatesCount=countif(Classification !has "Critical" and Classification !has "Security" and UpdateState=~"Needed"), lastAssessedTime=max(TimeGenerated), lastUpdateAgentSeenTime="" by SourceComputerId
    | extend compliance=iff(missingCriticalUpdatesCount > 0 or missingSecurityUpdatesCount > 0, 2, 1)
    | extend ComplianceOrder=iff(missingCriticalUpdatesCount > 0 or missingSecurityUpdatesCount > 0 or missingOtherUpdatesCount > 0, 1, 3)
)
on SourceComputerId
| project id=SourceComputerId, displayName=Computer, sourceComputerId=SourceComputerId, scopedToUpdatesSolution=true, missingCriticalUpdatesCount=coalesce(missingCriticalUpdatesCount, -1), missingSecurityUpdatesCount=coalesce(missingSecurityUpdatesCount, -1), missingOtherUpdatesCount=coalesce(missingOtherUpdatesCount, -1), compliance=coalesce(compliance, 4), lastAssessedTime, lastUpdateAgentSeenTime, osType=1, environment=iff(ComputerEnvironment=~"Azure", 1, 2), ComplianceOrder=coalesce(ComplianceOrder, 2)
| union(Heartbeat
| where TimeGenerated>ago(12h) and OSType=~"Windows" and notempty(Computer)
| summarize arg_max(TimeGenerated, Solutions, Computer, ResourceId, ComputerEnvironment, VMUUID) by SourceComputerId
| where Solutions has "updates"
| extend vmuuId=VMUUID, azureResourceId=ResourceId, osType=2, environment=iff(ComputerEnvironment=~"Azure", 1, 2), scopedToUpdatesSolution=true, lastUpdateAgentSeenTime=""
| join kind=leftouter
(
    Update
    | where TimeGenerated>ago(14h) and OSType!="Linux" and SourceComputerId in ((Heartbeat
    | where TimeGenerated>ago(12h) and OSType=~"Windows" and notempty(Computer)
    | summarize arg_max(TimeGenerated, Solutions) by SourceComputerId
    | where Solutions has "updates"
    | distinct SourceComputerId))
    | summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification, Title, Optional, Approved, Computer, ComputerEnvironment) by Computer, SourceComputerId, UpdateID
    | summarize Computer=any(Computer), ComputerEnvironment=any(ComputerEnvironment), missingCriticalUpdatesCount=countif(Classification has "Critical" and UpdateState=~"Needed" and Approved!=false), missingSecurityUpdatesCount=countif(Classification has "Security" and UpdateState=~"Needed" and Approved!=false), missingOtherUpdatesCount=countif(Classification !has "Critical" and Classification !has "Security" and UpdateState=~"Needed" and Optional==false and Approved!=false), lastAssessedTime=max(TimeGenerated), lastUpdateAgentSeenTime="" by SourceComputerId
    | extend compliance=iff(missingCriticalUpdatesCount > 0 or missingSecurityUpdatesCount > 0, 2, 1)
    | extend ComplianceOrder=iff(missingCriticalUpdatesCount > 0 or missingSecurityUpdatesCount > 0 or missingOtherUpdatesCount > 0, 1, 3)
)
on SourceComputerId
| project id=SourceComputerId, displayName=Computer, sourceComputerId=SourceComputerId, scopedToUpdatesSolution=true, missingCriticalUpdatesCount=coalesce(missingCriticalUpdatesCount, -1), missingSecurityUpdatesCount=coalesce(missingSecurityUpdatesCount, -1), missingOtherUpdatesCount=coalesce(missingOtherUpdatesCount, -1), compliance=coalesce(compliance, 4), lastAssessedTime, lastUpdateAgentSeenTime, osType=2, environment=iff(ComputerEnvironment=~"Azure", 1, 2), ComplianceOrder=coalesce(ComplianceOrder, 2) )
| order by ComplianceOrder asc, missingCriticalUpdatesCount desc, missingSecurityUpdatesCount desc, missingOtherUpdatesCount desc, displayName asc
| project-away ComplianceOrder

누락된 업데이트 목록

Update
| where TimeGenerated>ago(5h) and OSType=="Linux" and SourceComputerId in ((Heartbeat
| where TimeGenerated>ago(12h) and OSType=="Linux" and notempty(Computer)
| summarize arg_max(TimeGenerated, Solutions) by SourceComputerId
| where Solutions has "updates"
| distinct SourceComputerId))
| summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification, BulletinUrl, BulletinID) by SourceComputerId, Product, ProductArch
| where UpdateState=~"Needed"
| project-away UpdateState, TimeGenerated
| summarize computersCount=dcount(SourceComputerId, 2), ClassificationWeight=max(iff(Classification has "Critical", 4, iff(Classification has "Security", 2, 1))) by id=strcat(Product, "_", ProductArch), displayName=Product, productArch=ProductArch, classification=Classification, InformationId=BulletinID, InformationUrl=tostring(split(BulletinUrl, ";", 0)[0]), osType=1
| union(Update
| where TimeGenerated>ago(14h) and OSType!="Linux" and (Optional==false or Classification has "Critical" or Classification has "Security") and SourceComputerId in ((Heartbeat
| where TimeGenerated>ago(12h) and OSType=~"Windows" and notempty(Computer)
| summarize arg_max(TimeGenerated, Solutions) by SourceComputerId
| where Solutions has "updates"
| distinct SourceComputerId))
| summarize hint.strategy=partitioned arg_max(TimeGenerated, UpdateState, Classification, Title, KBID, PublishedDate, Approved) by Computer, SourceComputerId, UpdateID
| where UpdateState=~"Needed" and Approved!=false
| project-away UpdateState, Approved, TimeGenerated
| summarize computersCount=dcount(SourceComputerId, 2), displayName=any(Title), publishedDate=min(PublishedDate), ClassificationWeight=max(iff(Classification has "Critical", 4, iff(Classification has "Security", 2, 1))) by id=strcat(UpdateID, "_", KBID), classification=Classification, InformationId=strcat("KB", KBID), InformationUrl=iff(isnotempty(KBID), strcat("https://support.microsoft.com/kb/", KBID), ""), osType=2)
| sort by ClassificationWeight desc, computersCount desc, displayName asc
| extend informationLink=(iff(isnotempty(InformationId) and isnotempty(InformationUrl), toobject(strcat('{ "uri": "', InformationUrl, '", "text": "', InformationId, '", "target": "blank" }')), toobject('')))
| project-away ClassificationWeight, InformationId, InformationUrl

다음 단계