source/Public/Set-RJLogAnalyticsWorkspace.ps1

function Set-RJLogAnalyticsWorkspace {
    <#
    .SYNOPSIS
    Deploys RealmJoin Log Analytics Workspace infrastructure to Azure.
 
    .DESCRIPTION
    Deploys the RealmJoin Log Analytics Workspace with custom tables and conditional
    Data Collection Rules (DCRs) for audit logs, runbook logs, and operational logs.
 
    Uses bundled ARM templates (JSON). Device code authentication is required for proper
    consent with ARM Microsoft Graph extension operations.
 
    Prerequisites:
    - Az.Accounts and Az.Resources PowerShell modules
    - Resource group must already exist
 
    .PARAMETER ResourceGroupName
    The name of the resource group to deploy to (must exist).
 
    .PARAMETER WorkspaceName
    Optional. The name of the Log Analytics Workspace. If not provided, a unique name is auto-generated.
 
    .PARAMETER SubscriptionId
    Optional. The Azure subscription ID to deploy to. If not provided, uses the current context.
 
    .PARAMETER DeployAuditLogsDCR
    Whether to deploy the audit logs DCR and custom table. Default: true.
 
    .PARAMETER DeployRunbookLogsDCR
    Whether to deploy the runbook logs DCR and custom table. Default: true.
 
    .PARAMETER DeployOperationalLogsDCR
    Whether to deploy the operational logs DCR and custom table. Default: true.
 
    .PARAMETER Token
    Optional. The RealmJoin onboarding token. When provided, registers the workspace with RealmJoin API.
 
    .PARAMETER WhatIf
    Shows what would be deployed without actually performing the deployment.
 
    .EXAMPLE
    Set-RJLogAnalyticsWorkspace -ResourceGroupName "rg-realmjoin"
 
    .EXAMPLE
    Set-RJLogAnalyticsWorkspace -ResourceGroupName "rg-realmjoin" -WorkspaceName "la-rj-auditlogs"
 
    .EXAMPLE
    Set-RJLogAnalyticsWorkspace -ResourceGroupName "rg-realmjoin" -DeployAuditLogsDCR $true -DeployRunbookLogsDCR $true -DeployOperationalLogsDCR $true
 
    .EXAMPLE
    Set-RJLogAnalyticsWorkspace -ResourceGroupName "rg-realmjoin" -WhatIf
    Shows what resources would be deployed without actually deploying.
 
    .EXAMPLE
    Set-RJLogAnalyticsWorkspace -ResourceGroupName "rg-realmjoin" -Token "your-token"
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)]
        [string]$ResourceGroupName,

        [string]$WorkspaceName,

        [string]$SubscriptionId,

        [bool]$DeployAuditLogsDCR = $DefaultDeployAuditLogsDCR,

        [bool]$DeployRunbookLogsDCR = $DefaultDeployRunbookLogsDCR,

        [bool]$DeployOperationalLogsDCR = $DefaultDeployOperationalLogsDCR,

        [string]$Token
    )

    begin {
        Write-Verbose "Set-RJLogAnalyticsWorkspace: Starting"
    }

    process {
        if (-not (Test-RJModuleVersion)) {
            # Module is outdated - exit gracefully without throwing
            return
        }

        # Initialize Az modules
        Write-Information "Initializing required Azure modules..."
        if (-not (Initialize-RequiredModule)) {
            Write-Verbose "Azure module initialization failed - cannot proceed"
            return
        }

        # Connect to Azure
        $connectParams = @{}
        if ($SubscriptionId) { $connectParams.SubscriptionId = $SubscriptionId }
        $context = Connect-RJAzureContext @connectParams
        if ($null -eq $context) {
            Write-Information "Operation cancelled."
            return
        }

        # Verify resource group
        $null = Test-ResourceGroup -ResourceGroupName $ResourceGroupName

        if ($PSCmdlet.ShouldProcess("Resource Group: $ResourceGroupName", "Deploy RealmJoin Log Analytics Workspace")) {
            Write-Information ""
            Write-Information "============================================"
            Write-Information "RealmJoin Log Analytics Workspace Deployment"
            Write-Information "============================================"
            Write-Information ""

            # Deploy
            $deployParams = @{
                ResourceGroupName       = $ResourceGroupName
                DeployAuditLogsDCR      = $DeployAuditLogsDCR
                DeployRunbookLogsDCR    = $DeployRunbookLogsDCR
                DeployOperationalLogsDCR = $DeployOperationalLogsDCR
            }
            if ($WorkspaceName) {
                $deployParams.WorkspaceName = $WorkspaceName
            }

            $result = Set-RJLogAnalyticsResource @deployParams

            if (-not $result.Success) {
                throw "Log Analytics Workspace deployment failed"
            }

            # Optional API registration
            if ($Token) {
                Write-Information ""
                Write-Information "--- RealmJoin API Registration ---"
                $additionalData = @{
                    tenantId            = $context.TenantId
                    subscriptionId      = $context.SubscriptionId
                    resourceGroupName   = $ResourceGroupName
                    workspaceName       = $result.Outputs.WorkspaceName
                    customerWorkspaceId = $result.Outputs.CustomerId
                }

                if ($DeployAuditLogsDCR) {
                    $additionalData.auditLogsDataCollectionEndpoint        = $result.Outputs.AuditLogsIngestionEndpoint
                    $additionalData.auditLogsDataCollectionRuleImmutableId = $result.Outputs.AuditLogsDcrImmutableId
                    $additionalData.auditLogsStreamName                    = $result.Outputs.AuditLogsStreamName
                    $additionalData.auditLogsDataCollectionRuleName        = $result.Outputs.AuditLogsDcrName
                }

                if ($DeployRunbookLogsDCR) {
                    $additionalData.runbookLogsDataCollectionEndpoint        = $result.Outputs.RunbookLogsIngestionEndpoint
                    $additionalData.runbookLogsDataCollectionRuleImmutableId = $result.Outputs.RunbookLogsDcrImmutableId
                    $additionalData.runbookLogsStreamName                    = $result.Outputs.RunbookLogsStreamName
                    $additionalData.runbookLogsDataCollectionRuleName        = $result.Outputs.RunbookLogsDcrName
                }

                if ($DeployOperationalLogsDCR) {
                    $additionalData.operationalLogsDataCollectionEndpoint        = $result.Outputs.OperationalLogsIngestionEndpoint
                    $additionalData.operationalLogsDataCollectionRuleImmutableId = $result.Outputs.OperationalLogsDcrImmutableId
                    $additionalData.operationalLogsStreamName                    = $result.Outputs.OperationalLogsStreamName
                    $additionalData.operationalLogsDataCollectionRuleName        = $result.Outputs.OperationalLogsDcrName
                }

                $schemaVersionsPath = Get-ArmTemplatePath -RelativePath "log-analytics-workspace/schema-versions.json"
                $schemaVersions = Get-Content $schemaVersionsPath -Raw | ConvertFrom-Json

                if ($DeployAuditLogsDCR) {
                    $additionalData.auditLogsSchemaVersion     = $schemaVersions.auditLogs.version
                    $additionalData.auditLogsSchemaLastUpdated = $schemaVersions.auditLogs.lastUpdated
                }
                if ($DeployRunbookLogsDCR) {
                    $additionalData.runbookLogsSchemaVersion     = $schemaVersions.runbookLogs.version
                    $additionalData.runbookLogsSchemaLastUpdated = $schemaVersions.runbookLogs.lastUpdated
                }
                if ($DeployOperationalLogsDCR) {
                    $additionalData.operationalLogsSchemaVersion     = $schemaVersions.operationalLogs.version
                    $additionalData.operationalLogsSchemaLastUpdated = $schemaVersions.operationalLogs.lastUpdated
                }

                Invoke-RJOnboarding -Token $Token -ApiUrl (Get-RealmJoinTenantAzureResourcesOnboardingApiUrl) -AdditionalData $additionalData
            }

            # Summary
            Write-Information ""
            Write-Information "============================================"
            Write-Information "Deployment Complete!"
            Write-Information "============================================"
            Write-Information "Workspace Name: $($result.Outputs.WorkspaceName)"
            Write-Information "Workspace ID: $($result.Outputs.WorkspaceId)"
            Write-Information "Customer ID: $($result.Outputs.CustomerId)"

            if ($DeployAuditLogsDCR) {
                Write-Information "Audit Logs DCR: $($result.Outputs.AuditLogsDcrImmutableId)"
            }
            if ($DeployRunbookLogsDCR) {
                Write-Information "Runbook Logs DCR: $($result.Outputs.RunbookLogsDcrImmutableId)"
            }
            if ($DeployOperationalLogsDCR) {
                Write-Information "Operational Logs DCR: $($result.Outputs.OperationalLogsDcrImmutableId)"
            }
            Write-Information ""
        }
        else {
            # WhatIf: show analysis
            $analysis = Get-RJAzureResourceAnalysis -ResourceGroupName $ResourceGroupName `
                -DeployAutomationAccount $false `
                -DeployLogAnalytics $true `
                -WorkspaceName $WorkspaceName `
                -DeployAuditLogsDCR $DeployAuditLogsDCR `
                -DeployRunbookLogsDCR $DeployRunbookLogsDCR `
                -DeployOperationalLogsDCR $DeployOperationalLogsDCR
            Show-RJAzureResourceAnalysis -Analysis $analysis
        }
    }

    end {
        Write-Verbose "Set-RJLogAnalyticsWorkspace: Completed"
    }
}