이 문서에서는 로그 수집 API를 사용하여 Azure Monitor 로그에 데이터를 보내기 전에 필요한 모든 리소스를 설정하는 PowerShell 스크립트를 제공합니다.
참고
Microsoft MVP인 Morten Waltorp Knudsen은 이 문서에 기여하고 자료 피드백을 제공했습니다. 로그 수집 API의 설정 및 지속적인 사용을 자동화하는 방법에 대한 예제는 Morten의 AzLogDcrIngestPS PowerShell 모듈을 참조하세요.
리소스 및 권한 만들기
스크립트는 이러한 리소스가 아직 없는 경우 만듭니다.
Log Analytics 작업 영역 및 Log Analytics 작업 영역에 대한 리소스 그룹
Log Analytics 작업 영역이 이미 있을 수 있습니다. 이 경우 스크립트가 작업 영역과 동일한 지역에 있는 다른 리소스를 설정할 수 있도록 작업 영역 세부 정보를 제공합니다.
API에 대해 인증하는 Microsoft Entra 애플리케이션 및:
- Microsoft Entra 애플리케이션의 서비스 주체
- Microsoft Entra 애플리케이션에 대한 비밀
데이터를 수신하기 위한 DCE(데이터 수집 엔드포인트) 및 데이터 수집 엔드포인트에 대한 리소스 그룹(Log Analytics 작업 영역과 동일한 지역)
Log Analytics 작업 영역과 동일한 지역에 있는 DCR(데이터 수집 규칙)에 대한 리소스 그룹
또한 스크립트는 다음 대상에 앱 Contributor
권한을 부여합니다.
- Log Analytics 작업 영역
- 데이터 수집 규칙에 대한 리소스 그룹
- 데이터 수집 엔드포인트에 대한 리소스 그룹
PowerShell 스크립트
#------------------------------------------------------------------------------------------------------------
# Prerequisite functions
#------------------------------------------------------------------------------------------------------------
Write-Output "Checking needed functions ... Please Wait !"
$ModuleCheck = Get-Module -Name Az.Resources -ListAvailable -ErrorAction SilentlyContinue
If (!($ModuleCheck))
{
Write-Output "Installing Az-module in CurrentUser scope ... Please Wait !"
Install-module -Name Az -Force -Scope CurrentUser
}
$ModuleCheck = Get-Module -Name Microsoft.Graph -ListAvailable -ErrorAction SilentlyContinue
If (!($ModuleCheck))
{
Write-Output "Installing Microsoft.Graph in CurrentUser scope ... Please Wait !"
Install-module -Name Microsoft.Graph -Force -Scope CurrentUser
}
<#
Install-module Az -Scope CurrentUser
Install-module Microsoft.Graph -Scope CurrentUser
install-module Az.portal -Scope CurrentUser
Import-module Az -Scope CurrentUser
Import-module Az.Accounts -Scope CurrentUser
Import-module Az.Resources -Scope CurrentUser
Import-module Microsoft.Graph.Applications -Scope CurrentUser
Import-Module Microsoft.Graph.DeviceManagement.Enrolment -Scope CurrentUser
#>
#----------------------------------------------------------------------------
# (1) Variables (Prerequisites, environment setup)
#----------------------------------------------------------------------------
$TenantId = "<your tenant ID>"
# Azure app registration
$AzureAppName = "Log-Ingestion-App"
$AzAppSecretName = "Log-Ingestion-App secret"
# Log Analytics workspace
$LogAnalyticsSubscription = "<Log Analytics workspace ID>"
$LogAnalyticsResourceGroup = "<Log Analytics workspace resource group>"
$LoganalyticsWorkspaceName = "<Log Analytics workspace name>"
$LoganalyticsLocation = "<Log Analytics workspace location>"
# Data collection endpoint
$AzDceName = "dce-log-ingestion-demo"
$AzDceResourceGroup = "rg-dce-log-ingestion-demo"
# Data collection rule
$AzDcrResourceGroup = "rg-dcr-log-ingestion-demo"
$AzDcrPrefix = "demo"
$VerbosePreference = "SilentlyContinue" # "Continue"
#----------------------------------------------------------------------------
# (2) Connectivity
#----------------------------------------------------------------------------
# Connect to Azure
Connect-AzAccount -Tenant $TenantId -WarningAction SilentlyContinue
# Get access token
$AccessToken = Get-AzAccessToken -ResourceUrl https://management.azure.com/
$AccessToken = $AccessToken.Token
# Build headers for Azure REST API with access token
$Headers = @{
"Authorization"="Bearer $($AccessToken)"
"Content-Type"="application/json"
}
# Connect to Microsoft Graph
$MgScope = @(
"Application.ReadWrite.All",`
"Directory.Read.All",`
"Directory.AccessAsUser.All",
"RoleManagement.ReadWrite.Directory"
)
Connect-MgGraph -TenantId $TenantId -Scopes $MgScope
#-------------------------------------------------------------------------------------------
# (3) Prerequisites - deployment of environment (if missing)
#-------------------------------------------------------------------------------------------
<#
This section deploys all resources needed for ingesting logs using the Log Ingestion API.
The deployment includes the following steps:
(1) Create a resource group for the Log Analytics workspace
(2) Create the Log Analytics workspace
(3) Create an Azure App registration to send data to Azure Monitor Logs
(4) Create a service principal on the app
(5) Create a secret for the app
(6) Create a resource group for the data collection endpoint (DCE) in the same region as the Log Analytics workspace
(7) Create a resource group for data collection rules (DCR) in the same region as the Log Analytics workspace
(8) Create data collection endpoint (DCE) in same region as Log Analytics workspace
(9) Grant the Azure app permissions to the Log Analytics workspace
(10) Grant the Azure app permissions to the resource group for data collection rules (DCR)
(11) Grant the Azure app permissions to the resource group for data collection endpoints (DCE)
#>
#-------------------------------------------------------------------------------------
# Azure context
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating Azure context is subscription [ $($LogAnalyticsSubscription) ]"
$AzContext = Get-AzContext
If ($AzContext.Subscription -ne $LogAnalyticsSubscription )
{
Write-Output ""
Write-Output "Switching Azure context to subscription [ $($LogAnalyticsSubscription) ]"
$AzContext = Set-AzContext -Subscription $LogAnalyticsSubscription -Tenant $TenantId
}
#-------------------------------------------------------------------------------------
# Create the resource group for Log Analytics workspace
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating Azure resource group exist [ $($LogAnalyticsResourceGroup) ]"
try {
Get-AzResourceGroup -Name $LogAnalyticsResourceGroup -ErrorAction Stop
} catch {
Write-Output ""
Write-Output "Creating Azure resource group [ $($LogAnalyticsResourceGroup) ]"
New-AzResourceGroup -Name $LogAnalyticsResourceGroup -Location $LoganalyticsLocation
}
#-------------------------------------------------------------------------------------
# Create the workspace
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating Log Analytics workspace exist [ $($LoganalyticsWorkspaceName) ]"
try {
$LogWorkspaceInfo = Get-AzOperationalInsightsWorkspace -Name $LoganalyticsWorkspaceName -ResourceGroupName $LogAnalyticsResourceGroup -ErrorAction Stop
} catch {
Write-Output ""
Write-Output "Creating Log Analytics workspace [ $($LoganalyticsWorkspaceName) ] in $LogAnalyticsResourceGroup"
New-AzOperationalInsightsWorkspace -Location $LoganalyticsLocation -Name $LoganalyticsWorkspaceName -Sku PerGB2018 -ResourceGroupName $LogAnalyticsResourceGroup
}
#-------------------------------------------------------------------------------------
# Get workspace details
#-------------------------------------------------------------------------------------
$LogWorkspaceInfo = Get-AzOperationalInsightsWorkspace -Name $LoganalyticsWorkspaceName -ResourceGroupName $LogAnalyticsResourceGroup
$LogAnalyticsWorkspaceResourceId = $LogWorkspaceInfo.ResourceId
#-------------------------------------------------------------------------------------
# Create Azure app registration
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating Azure App [ $($AzureAppName) ]"
$AppCheck = Get-MgApplication -Filter "DisplayName eq '$AzureAppName'" -ErrorAction Stop
If ($AppCheck -eq $null)
{
Write-Output ""
Write-host "Creating Azure App [ $($AzureAppName) ]"
$AzureApp = New-MgApplication -DisplayName $AzureAppName
}
#-------------------------------------------------------------------------------------
# Create service principal on Azure app
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating Azure Service Principal on App [ $($AzureAppName) ]"
$AppInfo = Get-MgApplication -Filter "DisplayName eq '$AzureAppName'"
$AppId = $AppInfo.AppId
$ObjectId = $AppInfo.Id
$ServicePrincipalCheck = Get-MgServicePrincipal -Filter "AppId eq '$AppId'"
If ($ServicePrincipalCheck -eq $null)
{
Write-Output ""
Write-host "Creating Azure Service Principal on App [ $($AzureAppName) ]"
$ServicePrincipal = New-MgServicePrincipal -AppId $AppId
}
#-------------------------------------------------------------------------------------
# Create secret on Azure app
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating Azure Secret on App [ $($AzureAppName) ]"
$AppInfo = Get-MgApplication -Filter "AppId eq '$AppId'"
$AppId = $AppInfo.AppId
$ObjectId = $AppInfo.Id
If ($AzAppSecretName -notin $AppInfo.PasswordCredentials.DisplayName)
{
Write-Output ""
Write-host "Creating Azure Secret on App [ $($AzureAppName) ]"
$passwordCred = @{
displayName = $AzAppSecretName
endDateTime = (Get-Date).AddYears(1)
}
$AzAppSecret = (Add-MgApplicationPassword -applicationId $ObjectId -PasswordCredential $passwordCred).SecretText
Write-Output ""
Write-Output "Secret with name [ $($AzAppSecretName) ] created on app [ $($AzureAppName) ]"
Write-Output $AzAppSecret
Write-Output ""
Write-Output "AppId for app [ $($AzureAppName) ] is"
Write-Output $AppId
}
#-------------------------------------------------------------------------------------
# Create a resource group for data collection endpoints (DCE) in the same region as the Log Analytics workspace
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating Azure resource group exist [ $($AzDceResourceGroup) ]"
try {
Get-AzResourceGroup -Name $AzDceResourceGroup -ErrorAction Stop
} catch {
Write-Output ""
Write-Output "Creating Azure resource group [ $($AzDceResourceGroup) ]"
New-AzResourceGroup -Name $AzDceResourceGroup -Location $LoganalyticsLocation
}
#-------------------------------------------------------------------------------------
# Create a resource group for data collection rules (DCR) in the same region as the Log Analytics workspace
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating Azure resource group exist [ $($AzDcrResourceGroup) ]"
try {
Get-AzResourceGroup -Name $AzDcrResourceGroup -ErrorAction Stop
} catch {
Write-Output ""
Write-Output "Creating Azure resource group [ $($AzDcrResourceGroup) ]"
New-AzResourceGroup -Name $AzDcrResourceGroup -Location $LoganalyticsLocation
}
#-------------------------------------------------------------------------------------
# Create data collection endpoint
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Validating data collection endpoint exist [ $($AzDceName) ]"
$DceUri = "https://management.azure.com" + "/subscriptions/" + $LogAnalyticsSubscription + "/resourceGroups/" + $AzDceResourceGroup + "/providers/Microsoft.Insights/dataCollectionEndpoints/" + $AzDceName + "?api-version=2022-06-01"
Try
{
Invoke-RestMethod -Uri $DceUri -Method GET -Headers $Headers
}
Catch
{
Write-Output ""
Write-Output "Creating/updating DCE [ $($AzDceName) ]"
$DceObject = [pscustomobject][ordered]@{
properties = @{
description = "DCE for LogIngest to LogAnalytics $LoganalyticsWorkspaceName"
networkAcls = @{
publicNetworkAccess = "Enabled"
}
}
location = $LogAnalyticsLocation
name = $AzDceName
type = "Microsoft.Insights/dataCollectionEndpoints"
}
$DcePayload = $DceObject | ConvertTo-Json -Depth 20
$DceUri = "https://management.azure.com" + "/subscriptions/" + $LogAnalyticsSubscription + "/resourceGroups/" + $AzDceResourceGroup + "/providers/Microsoft.Insights/dataCollectionEndpoints/" + $AzDceName + "?api-version=2022-06-01"
Try
{
Invoke-WebRequest -Uri $DceUri -Method PUT -Body $DcePayload -Headers $Headers
}
Catch
{
}
}
#-------------------------------------------------------------------------------------
# Sleeping 1 min to let Azure AD replicate before delegation
#-------------------------------------------------------------------------------------
# Write-Output "Sleeping 1 min to let Azure AD replicate before doing delegation"
# Start-Sleep -s 60
#-------------------------------------------------------------------------------------
# Grant the Azure app permissions to the Log Analytics workspace
# Needed for table management - not needed for log ingestion - for simplicity, it's set up when there's one app
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Setting Contributor permissions for app [ $($AzureAppName) ] on the Log Analytics workspace [ $($LoganalyticsWorkspaceName) ]"
$LogWorkspaceInfo = Get-AzOperationalInsightsWorkspace -Name $LoganalyticsWorkspaceName -ResourceGroupName $LogAnalyticsResourceGroup
$LogAnalyticsWorkspaceResourceId = $LogWorkspaceInfo.ResourceId
$ServicePrincipalObjectId = (Get-MgServicePrincipal -Filter "AppId eq '$AppId'").Id
$DcrRgResourceId = (Get-AzResourceGroup -Name $AzDcrResourceGroup).ResourceId
# Contributor on Log Analytics workspace
$guid = (new-guid).guid
$ContributorRoleId = "b24988ac-6180-42a0-ab88-20f7382dd24c" # Contributor
$roleDefinitionId = "/subscriptions/$($LogAnalyticsSubscription)/providers/Microsoft.Authorization/roleDefinitions/$($ContributorRoleId)"
$roleUrl = "https://management.azure.com" + $LogAnalyticsWorkspaceResourceId + "/providers/Microsoft.Authorization/roleAssignments/$($Guid)?api-version=2018-07-01"
$roleBody = @{
properties = @{
roleDefinitionId = $roleDefinitionId
principalId = $ServicePrincipalObjectId
scope = $LogAnalyticsWorkspaceResourceId
}
}
$jsonRoleBody = $roleBody | ConvertTo-Json -Depth 6
$result = try
{
Invoke-RestMethod -Uri $roleUrl -Method PUT -Body $jsonRoleBody -headers $Headers -ErrorAction SilentlyContinue
}
catch
{
}
#-------------------------------------------------------------------------------------
# Grant the Azure app permissions to the DCR resource group
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Setting Contributor permissions for app [ $($AzureAppName) ] on resource group [ $($AzDcrResourceGroup) ]"
$ServicePrincipalObjectId = (Get-MgServicePrincipal -Filter "AppId eq '$AppId'").Id
$AzDcrRgResourceId = (Get-AzResourceGroup -Name $AzDcrResourceGroup).ResourceId
# Contributor
$guid = (new-guid).guid
$ContributorRoleId = "b24988ac-6180-42a0-ab88-20f7382dd24c" # Contributor
$roleDefinitionId = "/subscriptions/$($LogAnalyticsSubscription)/providers/Microsoft.Authorization/roleDefinitions/$($ContributorRoleId)"
$roleUrl = "https://management.azure.com" + $AzDcrRgResourceId + "/providers/Microsoft.Authorization/roleAssignments/$($Guid)?api-version=2018-07-01"
$roleBody = @{
properties = @{
roleDefinitionId = $roleDefinitionId
principalId = $ServicePrincipalObjectId
scope = $AzDcrRgResourceId
}
}
$jsonRoleBody = $roleBody | ConvertTo-Json -Depth 6
$result = try
{
Invoke-RestMethod -Uri $roleUrl -Method PUT -Body $jsonRoleBody -headers $Headers -ErrorAction SilentlyContinue
}
catch
{
}
Write-Output ""
Write-Output "Setting Monitoring Metrics Publisher permissions for app [ $($AzureAppName) ] on RG [ $($AzDcrResourceGroup) ]"
# Monitoring Metrics Publisher
$guid = (new-guid).guid
$monitorMetricsPublisherRoleId = "3913510d-42f4-4e42-8a64-420c390055eb"
$roleDefinitionId = "/subscriptions/$($LogAnalyticsSubscription)/providers/Microsoft.Authorization/roleDefinitions/$($monitorMetricsPublisherRoleId)"
$roleUrl = "https://management.azure.com" + $AzDcrRgResourceId + "/providers/Microsoft.Authorization/roleAssignments/$($Guid)?api-version=2018-07-01"
$roleBody = @{
properties = @{
roleDefinitionId = $roleDefinitionId
principalId = $ServicePrincipalObjectId
scope = $AzDcrRgResourceId
}
}
$jsonRoleBody = $roleBody | ConvertTo-Json -Depth 6
$result = try
{
Invoke-RestMethod -Uri $roleUrl -Method PUT -Body $jsonRoleBody -headers $Headers -ErrorAction SilentlyContinue
}
catch
{
}
#-------------------------------------------------------------------------------------
# Grant the Azure app permissions to the DCE resource group
#-------------------------------------------------------------------------------------
Write-Output ""
Write-Output "Setting Contributor permissions for app [ $($AzDceName) ] on RG [ $($AzDceResourceGroup) ]"
$ServicePrincipalObjectId = (Get-MgServicePrincipal -Filter "AppId eq '$AppId'").Id
$AzDceRgResourceId = (Get-AzResourceGroup -Name $AzDceResourceGroup).ResourceId
# Contributor
$guid = (new-guid).guid
$ContributorRoleId = "b24988ac-6180-42a0-ab88-20f7382dd24c" # Contributor
$roleDefinitionId = "/subscriptions/$($LogAnalyticsSubscription)/providers/Microsoft.Authorization/roleDefinitions/$($ContributorRoleId)"
$roleUrl = "https://management.azure.com" + $AzDceRgResourceId + "/providers/Microsoft.Authorization/roleAssignments/$($Guid)?api-version=2018-07-01"
$roleBody = @{
properties = @{
roleDefinitionId = $roleDefinitionId
principalId = $ServicePrincipalObjectId
scope = $AzDceRgResourceId
}
}
$jsonRoleBody = $roleBody | ConvertTo-Json -Depth 6
$result = try
{
Invoke-RestMethod -Uri $roleUrl -Method PUT -Body $jsonRoleBody -headers $Headers -ErrorAction SilentlyContinue
}
catch
{
}
#-----------------------------------------------------------------------------------------------
# Summarize environment details
#-----------------------------------------------------------------------------------------------
# Azure App
Write-Output ""
Write-Output "Tenant Id:"
Write-Output $TenantId
# Azure App
$AppInfo = Get-MgApplication -Filter "DisplayName eq '$AzureAppName'"
$AppId = $AppInfo.AppId
$ObjectId = $AppInfo.Id
Write-Output ""
Write-Output "Log Ingestion Azure App name:"
Write-Output $AzureAppName
Write-Output ""
Write-Output "Log Ingestion Azure App ID:"
Write-Output $AppId
Write-Output ""
If ($AzAppSecret)
{
Write-Output "LogIngestion Azure App secret:"
Write-Output $AzAppSecret
}
Else
{
Write-Output "Log Ingestion Azure App secret:"
Write-Output "N/A (new secret must be made)"
}
# Azure Service Principal for App
$ServicePrincipalObjectId = (Get-MgServicePrincipal -Filter "AppId eq '$AppId'").Id
Write-Output ""
Write-Output "Log Ingestion service principal Object ID for app:"
Write-Output $ServicePrincipalObjectId
# Azure Loganalytics
Write-Output ""
$LogWorkspaceInfo = Get-AzOperationalInsightsWorkspace -Name $LoganalyticsWorkspaceName -ResourceGroupName $LogAnalyticsResourceGroup
$LogAnalyticsWorkspaceResourceId = $LogWorkspaceInfo.ResourceId
Write-Output ""
Write-Output "Log Analytics workspace resource ID:"
Write-Output $LogAnalyticsWorkspaceResourceId
# DCE
$DceUri = "https://management.azure.com" + "/subscriptions/" + $LogAnalyticsSubscription + "/resourceGroups/" + $AzDceResourceGroup + "/providers/Microsoft.Insights/dataCollectionEndpoints/" + $AzDceName + "?api-version=2022-06-01"
$DceObj = Invoke-RestMethod -Uri $DceUri -Method GET -Headers $Headers
$AzDceLogIngestionUri = $DceObj.properties.logsIngestion[0].endpoint
Write-Output ""
Write-Output "Data collection endpoint name:"
Write-Output $AzDceName
Write-Output ""
Write-Output "Data collection endpoint Log Ingestion URI:"
Write-Output $AzDceLogIngestionUri
Write-Output ""
Write-Output "-------------------------------------------------"