DefenderAPI.psm1
$script:ModuleRoot = $PSScriptRoot $script:ModuleVersion = (Import-PowerShellDataFile -Path "$($script:ModuleRoot)\DefenderAPI.psd1").ModuleVersion # Detect whether at some level dotsourcing was enforced $script:doDotSource = Get-PSFConfigValue -FullName DefenderAPI.Import.DoDotSource -Fallback $false if ($DefenderAPI_dotsourcemodule) { $script:doDotSource = $true } <# Note on Resolve-Path: All paths are sent through Resolve-Path/Resolve-PSFPath in order to convert them to the correct path separator. This allows ignoring path separators throughout the import sequence, which could otherwise cause trouble depending on OS. Resolve-Path can only be used for paths that already exist, Resolve-PSFPath can accept that the last leaf my not exist. This is important when testing for paths. #> # Detect whether at some level loading individual module files, rather than the compiled module was enforced $importIndividualFiles = Get-PSFConfigValue -FullName DefenderAPI.Import.IndividualFiles -Fallback $false if ($DefenderAPI_importIndividualFiles) { $importIndividualFiles = $true } if (Test-Path (Resolve-PSFPath -Path "$($script:ModuleRoot)\..\.git" -SingleItem -NewChild)) { $importIndividualFiles = $true } if ("<was compiled>" -eq '<was not compiled>') { $importIndividualFiles = $true } function Import-ModuleFile { <# .SYNOPSIS Loads files into the module on module import. .DESCRIPTION This helper function is used during module initialization. It should always be dotsourced itself, in order to proper function. This provides a central location to react to files being imported, if later desired .PARAMETER Path The path to the file to load .EXAMPLE PS C:\> . Import-ModuleFile -File $function.FullName Imports the file stored in $function according to import policy #> [CmdletBinding()] Param ( [string] $Path ) $resolvedPath = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($Path).ProviderPath if ($doDotSource) { . $resolvedPath } else { $ExecutionContext.InvokeCommand.InvokeScript($false, ([scriptblock]::Create([io.file]::ReadAllText($resolvedPath))), $null, $null) } } #region Load individual files if ($importIndividualFiles) { # Execute Preimport actions foreach ($path in (& "$ModuleRoot\internal\scripts\preimport.ps1")) { . Import-ModuleFile -Path $path } # Import all internal functions foreach ($function in (Get-ChildItem "$ModuleRoot\internal\functions" -Filter "*.ps1" -Recurse -ErrorAction Ignore)) { . Import-ModuleFile -Path $function.FullName } # Import all public functions foreach ($function in (Get-ChildItem "$ModuleRoot\functions" -Filter "*.ps1" -Recurse -ErrorAction Ignore)) { . Import-ModuleFile -Path $function.FullName } # Execute Postimport actions foreach ($path in (& "$ModuleRoot\internal\scripts\postimport.ps1")) { . Import-ModuleFile -Path $path } # End it here, do not load compiled code below return } #endregion Load individual files #region Load compiled code <# This file loads the strings documents from the respective language folders. This allows localizing messages and errors. Load psd1 language files for each language you wish to support. Partial translations are acceptable - when missing a current language message, it will fallback to English or another available language. #> Import-PSFLocalizedString -Path "$($script:ModuleRoot)\en-us\*.psd1" -Module 'DefenderAPI' -Language 'en-US' enum SubnetCategory { Unknown = 0 Corporate = 1 Administrative = 2 Risky = 3 VPN = 4 CloudProvider = 5 Other = 6 } <# # Example: Register-PSFTeppScriptblock -Name "DefenderAPI.alcohol" -ScriptBlock { 'Beer','Mead','Whiskey','Wine','Vodka','Rum (3y)', 'Rum (5y)', 'Rum (7y)' } #> <# # Example: Register-PSFTeppArgumentCompleter -Command Get-Alcohol -Parameter Type -Name DefenderAPI.alcohol #> # Register-PSFTeppArgumentCompleter -Command Connect-DefenderAPIService -Parameter Service -Name DefenderAPI.Service function ConvertFrom-RestSubnet { <# .SYNOPSIS Converts subnet objects to look nice. .DESCRIPTION Converts subnet objects to look nice. .PARAMETER InputObject The rest response representing a subnet .EXAMPLE PS C:\> Invoke-RestRequest -Path "subnet/$idString" -ErrorAction Stop | ConvertFrom-RestSubnet Retrieves the specified subnet and converts it into something userfriendly #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] $InputObject ) process { if (-not $InputObject) { return } [PSCustomObject]@{ PSTypeName = 'DefenderAPI.Mdca.Subnet' ID = $InputObject._id Name = $InputObject.Name Subnets = $InputObject.subnets.originalString SubnetsOriginal = $InputObject.subnets Location = $InputObject.location Organization = $InputObject.organization Tags = $InputObject.tags.name TagsOriginal = $InputObject.tags Category = $InputObject.Category -as [SubnetCategory] LastModified = $InputObject.LastModified } } } function Set-MdcaToken { <# .SYNOPSIS Helper function that injects the MDCA ApiKey Token into the EntraAuth token cache. .DESCRIPTION Helper function that injects the MDCA ApiKey Token into the EntraAuth token cache. By default, EntraAuth only supports authentication flows via entra (hence the module name). With this command we can inject a fake EntraAuth token object that works for Invoke-EntraRequest. .PARAMETER Token The MDCA ApiKey / Token to inject into EntraAuth. .PARAMETER TenantName Name of the tenant, the token applies to. Used for building the API Service Url. .EXAMPLE PS C:\> Set-MdcaToken -Token $MdcaToken -TenantName $TenantName Injects the MDCA ApiKey Token into the EntraAuth token cache. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( [SecureString] $Token, [string] $TenantName ) process { $fakeToken = [PSCustomObject]@{ ServiceUrl = "https://$TenantName.portal.cloudappsecurity.com/api/v1" ApiKey = $Token Service = 'DefenderAPI.MDCA' } Add-Member -InputObject $fakeToken -MemberType ScriptMethod -Name GetHeader -Value { return @{ Authorization = "Token {0}" -f ([PSCredential]::new("Whatever", $this.ApiKey).GetNetworkCredential().Password) 'content-type' = 'application/json' } } & (Get-Module EntraAuth) { param ($Token) $script:_EntraTokens['DefenderAPI.MDCA'] = $Token } $fakeToken } } function ConvertFrom-AdvancedQuery { <# .SYNOPSIS Converts the output of an Advanced Hunting Query into something PowerShell compatible. .DESCRIPTION Converts the output of an Advanced Hunting Query into something PowerShell compatible. .PARAMETER Result The result of the Invoke-MdeAdvancedQuery command. .EXAMPLE PS C:\> Invoke-MdeRequest -Path $__path -Method post -Body $__body -Query $__query -RequiredScopes 'AdvancedQuery.Read' | ConvertFrom-AdvancedQuery Processes the return values provided by the advanced query. #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] [AllowNull()] $Result ) begin { $typeMapping = @{ String = '<direct>' Double = '<direct>' SByte = { $_ -as [bool] } DateTime = '<direct>' Object = '<direct>' } } process { if (-not $Result) { return } $properties = foreach ($item in $Result.Schema) { if ((-not $typeMapping[$item.Type]) -or $typeMapping[$item.Type] -eq '<direct>') { $item.Name continue } @{ Name = $item.Name Expression = $typeMapping[$item.Type] } } $Result.Results | Select-Object $properties | ForEach-Object { $_.PSObject.TypeNames.Insert(0, 'DefenderAPI.AdvancedQuery.Result') $_ } } } function ConvertTo-Hashtable { <# .SYNOPSIS Converts input objects into hashtables. .DESCRIPTION Converts input objects into hashtables. Allows explicitly including some properties only and remapping key-names as required. .PARAMETER Include Only select the specified properties. .PARAMETER Mapping Remap hashtable/property keys. This allows you to rename parameters before passing them through to other commands. Example: @{ Select = '$select' } This will map the "Select"-property/key on the input object to be '$select' on the output item. .PARAMETER InputObject The object to convert. .EXAMPLE PS C:\> $__body = $PSBoundParameters | ConvertTo-Hashtable -Include Name, UserID -Mapping $__mapping Converts the object $PSBoundParameters into a hashtable, including the keys "Name" and "UserID" and remapping them as specified in $__mapping #> [OutputType([hashtable])] [CmdletBinding()] param ( [AllowEmptyCollection()] [string[]] $Include, [Hashtable] $Mapping = @{ }, [Parameter(ValueFromPipeline = $true)] $InputObject ) process { $result = @{ } if ($InputObject -is [System.Collections.IDictionary]) { foreach ($pair in $InputObject.GetEnumerator()) { if ($pair.Key -notin $Include) { continue } if ($Mapping[$pair.Key]) { $result[$Mapping[$pair.Key]] = $pair.Value } else { $result[$pair.Key] = $pair.Value } } } else { foreach ($property in $InputObject.PSObject.Properties) { if ($property.Name -notin $Include) { continue } if ($Mapping[$property.Name]) { $result[$Mapping[$property.Name]] = $property.Value } else { $result[$property.Name] = $property.Value } } } $result } } function ConvertTo-QueryString { <# .SYNOPSIS Convert conditions in a hashtable to a Query string to append to a webrequest. .DESCRIPTION Convert conditions in a hashtable to a Query string to append to a webrequest. .PARAMETER QueryHash Hashtable of query modifiers - usually filter conditions - to include in a web request. .EXAMPLE PS C:\> ConvertTo-QueryString -QueryHash $Query Converts the conditions in the specified hashtable to a Query string to append to a webrequest. #> [OutputType([string])] [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [Hashtable] $QueryHash ) process { $elements = foreach ($pair in $QueryHash.GetEnumerator()) { '{0}={1}' -f $pair.Name, ($pair.Value -join ",") } '?{0}' -f ($elements -join '&') } } function Invoke-TerminatingException { <# .SYNOPSIS Throw a terminating exception in the context of the caller. .DESCRIPTION Throw a terminating exception in the context of the caller. Masks the actual code location from the end user in how the message will be displayed. .PARAMETER Cmdlet The $PSCmdlet variable of the calling command. .PARAMETER Message The message to show the user. .PARAMETER Exception A nested exception to include in the exception object. .PARAMETER Category The category of the error. .PARAMETER ErrorRecord A full error record that was caught by the caller. Use this when you want to rethrow an existing error. .EXAMPLE PS C:\> Invoke-TerminatingException -Cmdlet $PSCmdlet -Message 'Unknown calling module' Terminates the calling command, citing an unknown caller. #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] $Cmdlet, [string] $Message, [System.Exception] $Exception, [System.Management.Automation.ErrorCategory] $Category = [System.Management.Automation.ErrorCategory]::NotSpecified, [System.Management.Automation.ErrorRecord] $ErrorRecord ) process{ if ($ErrorRecord -and -not $Message) { $Cmdlet.ThrowTerminatingError($ErrorRecord) } $exceptionType = switch ($Category) { default { [System.Exception] } 'InvalidArgument' { [System.ArgumentException] } 'InvalidData' { [System.IO.InvalidDataException] } 'AuthenticationError' { [System.Security.Authentication.AuthenticationException] } 'InvalidOperation' { [System.InvalidOperationException] } } if ($Exception) { $newException = $Exception.GetType()::new($Message, $Exception) } elseif ($ErrorRecord) { $newException = $ErrorRecord.Exception.GetType()::new($Message, $ErrorRecord.Exception) } else { $newException = $exceptionType::new($Message) } $record = [System.Management.Automation.ErrorRecord]::new($newException, (Get-PSCallStack)[1].FunctionName, $Category, $Target) $Cmdlet.ThrowTerminatingError($record) } } function Assert-DefenderAPIConnection { <# .SYNOPSIS Asserts a connection has been established. .DESCRIPTION Asserts a connection has been established. Fails the calling command in a terminating exception if not connected yet. .PARAMETER Service The service to which a connection needs to be established. .PARAMETER Cmdlet The $PSCmdlet variable of the calling command. Used to execute the terminating exception in the caller scope if needed. .PARAMETER RequiredScopes Scopes needed, for better error messages. .EXAMPLE PS C:\> Assert-DefenderAPIConnection -Service 'Endpoint' -Cmdlet $PSCmdlet Silently does nothing if already connected to the specified defender service. Kills the calling command if not yet connected. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $Service, [Parameter(Mandatory = $true)] $Cmdlet, [AllowEmptyCollection()] [string[]] $RequiredScopes ) begin { $serviceMap = @{ Endpoint = 'DefenderAPI.Endpoint' Security = 'DefenderAPI.Security' MDCA = 'DefenderAPI.MDCA' } } process { $actualServiceName = $Service if ($serviceMap[$Service]) { $actualServiceName = $serviceMap[$Service] } if (Get-EntraToken -Service $actualServiceName) { return } $message = "Not connected yet! Use Connect-DefenderAPIService to establish a connection to '$Service' first." if ($RequiredScopes) { $message = $message + " Scopes required for this call: $($RequiredScopes -join ', ')" } Invoke-TerminatingException -Cmdlet $Cmdlet -Message $message -Category ConnectionError } } function Connect-DefenderAPI { <# .SYNOPSIS Establish a connection to the defender APIs. .DESCRIPTION Establish a connection to the defender APIs. Prerequisite before executing any requests / commands. .PARAMETER ClientID ID of the registered/enterprise application used for authentication. .PARAMETER TenantID The ID of the tenant/directory to connect to. .PARAMETER Scopes Any scopes to include in the request. Only used for interactive/delegate workflows, ignored for Certificate based authentication or when using Client Secrets. .PARAMETER Browser Use an interactive logon in your default browser. This is the default logon experience. .PARAMETER BrowserMode How the browser used for authentication is selected. Options: + Auto (default): Automatically use the default browser. + PrintLink: The link to open is printed on console and user selects which browser to paste it into (must be used on the same machine) .PARAMETER DeviceCode Use the Device Code delegate authentication flow. This will prompt the user to complete login via browser. .PARAMETER Certificate The Certificate object used to authenticate with. Part of the Application Certificate authentication workflow. .PARAMETER CertificateThumbprint Thumbprint of the certificate to authenticate with. The certificate must be stored either in the user or computer certificate store. Part of the Application Certificate authentication workflow. .PARAMETER CertificateName The name/subject of the certificate to authenticate with. The certificate must be stored either in the user or computer certificate store. The newest certificate with a private key will be chosen. Part of the Application Certificate authentication workflow. .PARAMETER CertificatePath Path to a PFX file containing the certificate to authenticate with. Part of the Application Certificate authentication workflow. .PARAMETER CertificatePassword Password to use to read a PFX certificate file. Only used together with -CertificatePath. Part of the Application Certificate authentication workflow. .PARAMETER ClientSecret The client secret configured in the registered/enterprise application. Part of the Client Secret Certificate authentication workflow. .PARAMETER Credential The username / password to authenticate with. Part of the Resource Owner Password Credential (ROPC) workflow. .PARAMETER VaultName Name of the Azure Key Vault from which to retrieve the certificate or client secret used for the authentication. Secrets retrieved from the vault are not cached, on token expiration they will be retrieved from the Vault again. In order for this flow to work, please ensure that you either have an active AzureKeyVault service connection, or are connected via Connect-AzAccount. .PARAMETER SecretName Name of the secret to use from the Azure Key Vault specified through the '-VaultName' parameter. In order for this flow to work, please ensure that you either have an active AzureKeyVault service connection, or are connected via Connect-AzAccount. .PARAMETER Identity Log on as the Managed Identity of the current system. Only works in environments with managed identities, such as Azure Function Apps or Runbooks. .PARAMETER IdentityID ID of the User-Managed Identity to connect as. https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity .PARAMETER IdentityType Type of the User-Managed Identity. .PARAMETER Service The service to connect to. Individual commands using Invoke-MdeRequest specify the service to use and thus identify the token needed. Defaults to: Endpoint .PARAMETER ServiceUrl The base url to the service connecting to. Used for authentication, scopes and executing requests. Defaults to: https://api.securitycenter.microsoft.com/api .PARAMETER MdcaToken Legacy API Token for Microsoft Defender for Cloud Apps. Please stop using this and migrate to modern authentication. .PARAMETER TenantName The name of the tenant you are connecting for. Used solely for connections to Microsoft Defender for Cloud Apps connections. If your fully qualified tenant name is "contoso.onmicrosoft.com", the value to provide is "contoso". This is used as the first element in the service url for MDCA connections. If that name just won't work, check in the defender portal settings, under cloud apps in the overview what the API url is. .EXAMPLE PS C:\> Connect-DefenderAPI -ClientID $clientID -TenantID $tenantID Establish a connection to the defender for endpoint API, prompting the user for login on their default browser. .EXAMPLE PS C:\> Connect-DefenderAPI -ClientID $clientID -TenantID $tenantID -Certificate $cert Establish a connection to the defender APIs using the provided certificate. .EXAMPLE PS C:\> Connect-DefenderAPI -ClientID $clientID -TenantID $tenantID -CertificatePath C:\secrets\certs\mde.pfx -CertificatePassword (Read-Host -AsSecureString) Establish a connection to the defender APIs using the provided certificate file. Prompts you to enter the certificate-file's password first. .EXAMPLE PS C:\> Connect-DefenderAPI -ClientID $clientID -TenantID $tenantID -ClientSecret $secret Establish a connection to the defender APIs using a client secret. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")] [CmdletBinding(DefaultParameterSetName = 'Browser')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'Browser')] [Parameter(Mandatory = $true, ParameterSetName = 'DeviceCode')] [Parameter(Mandatory = $true, ParameterSetName = 'AppCertificate')] [Parameter(Mandatory = $true, ParameterSetName = 'AppSecret')] [Parameter(Mandatory = $true, ParameterSetName = 'UsernamePassword')] [Parameter(Mandatory = $true, ParameterSetName = 'KeyVault')] [string] $ClientID, [Parameter(Mandatory = $true, ParameterSetName = 'Browser')] [Parameter(Mandatory = $true, ParameterSetName = 'DeviceCode')] [Parameter(Mandatory = $true, ParameterSetName = 'AppCertificate')] [Parameter(Mandatory = $true, ParameterSetName = 'AppSecret')] [Parameter(Mandatory = $true, ParameterSetName = 'UsernamePassword')] [Parameter(Mandatory = $true, ParameterSetName = 'KeyVault')] [string] $TenantID, [Parameter(ParameterSetName = 'Browser')] [Parameter(ParameterSetName = 'DeviceCode')] [Parameter(ParameterSetName = 'AppCertificate')] [Parameter(ParameterSetName = 'AppSecret')] [Parameter(ParameterSetName = 'UsernamePassword')] [string[]] $Scopes, [Parameter(ParameterSetName = 'Browser')] [switch] $Browser, [Parameter(ParameterSetName = 'Browser')] [ValidateSet('Auto','PrintLink')] [string] $BrowserMode = 'Auto', [Parameter(ParameterSetName = 'DeviceCode')] [switch] $DeviceCode, [Parameter(ParameterSetName = 'AppCertificate')] [System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate, [Parameter(ParameterSetName = 'AppCertificate')] [string] $CertificateThumbprint, [Parameter(ParameterSetName = 'AppCertificate')] [string] $CertificateName, [Parameter(ParameterSetName = 'AppCertificate')] [string] $CertificatePath, [Parameter(ParameterSetName = 'AppCertificate')] [System.Security.SecureString] $CertificatePassword, [Parameter(Mandatory = $true, ParameterSetName = 'AppSecret')] [System.Security.SecureString] $ClientSecret, [Parameter(Mandatory = $true, ParameterSetName = 'UsernamePassword')] [PSCredential] $Credential, [Parameter(Mandatory = $true, ParameterSetName = 'MdcaLegacyToken')] [securestring] $MdcaToken, [Parameter(Mandatory = $true, ParameterSetName = 'KeyVault')] [string] $VaultName, [Parameter(Mandatory = $true, ParameterSetName = 'KeyVault')] [string] $SecretName, [Parameter(Mandatory = $true, ParameterSetName = 'Identity')] [switch] $Identity, [Parameter(ParameterSetName = 'Identity')] [string] $IdentityID, [Parameter(ParameterSetName = 'Identity')] [ValidateSet('ClientID', 'ResourceID', 'PrincipalID')] [string] $IdentityType = 'ClientID', [Parameter(ParameterSetName = 'Browser')] [Parameter(ParameterSetName = 'DeviceCode')] [Parameter(ParameterSetName = 'AppCertificate')] [Parameter(ParameterSetName = 'AppSecret')] [Parameter(ParameterSetName = 'UsernamePassword')] [Parameter(ParameterSetName = 'KeyVault')] [Parameter(ParameterSetName = 'Identity')] [Parameter(Mandatory = $true, ParameterSetName = 'MdcaLegacyToken')] [string] $TenantName, [Parameter(ParameterSetName = 'Browser')] [Parameter(ParameterSetName = 'DeviceCode')] [Parameter(ParameterSetName = 'AppCertificate')] [Parameter(ParameterSetName = 'AppSecret')] [Parameter(ParameterSetName = 'UsernamePassword')] [Parameter(ParameterSetName = 'KeyVault')] [Parameter(ParameterSetName = 'Identity')] [ValidateSet('Endpoint', 'Security', 'MDCA')] [string[]] $Service = 'Endpoint', [Parameter(ParameterSetName = 'Browser')] [Parameter(ParameterSetName = 'DeviceCode')] [Parameter(ParameterSetName = 'AppCertificate')] [Parameter(ParameterSetName = 'AppSecret')] [Parameter(ParameterSetName = 'UsernamePassword')] [Parameter(ParameterSetName = 'KeyVault')] [Parameter(ParameterSetName = 'Identity')] [string] $ServiceUrl ) begin { if ($Service -contains 'MDCA' -and -not $TenantName) { Stop-PSFFunction -String 'Connect-DefenderAPI.Error.MdcaNoTenant' -EnableException $true -Cmdlet $PSCmdlet } if ($Service -contains 'MDCA' -or $MdcaToken) { $param = @{ Name = 'DefenderAPI.MDCA' ServiceUrl = "https://$TenantName.portal.cloudappsecurity.com/api/v1" Resource = '05a65629-4c1b-48c1-a78b-804c4abdd4af' DefaultScopes = @() Header = @{ 'content-type' = 'application/json' } HelpUrl = 'https://learn.microsoft.com/en-us/defender-cloud-apps/api-introduction' } Register-EntraService @param } } process { $actualServiceNames = foreach ($serviceName in $Service) { "DefenderAPI.$serviceName" } if ($MdcaToken) { Set-MdcaToken -Token $MdcaToken -TenantName $TenantName return } $param = $PSBoundParameters | ConvertTo-PSFHashtable -ReferenceCommand Connect-EntraService $param.Service = $actualServiceNames Connect-EntraService @param } } function Get-MdcaAlert { <# .SYNOPSIS List/Retrieve alerts .DESCRIPTION List/Retrieve alerts Either a specific alert by ID or a list by filter. .PARAMETER ID ID of the event to retrieve. .PARAMETER SortField Sort results by the specified field. By default, results are however sorted as the API backend choses. Options: date, severity .PARAMETER Descending By default, results are sorted in an ascending order (if sorting at all). This parameter reverses the sorting order. .PARAMETER Skip Skip the first X results. .PARAMETER Limit Return only X results in total. .PARAMETER Filter A custom filter as defined here: https://learn.microsoft.com/en-us/defender-cloud-apps/api-alerts#filters Example filter for open alerts of high severity: @{ alertOpen = @{ eq = $true } severity = @{ eq = 2 } } .EXAMPLE PS C:\> Get-MdcaAlert List all alerts. .EXAMPLE PS C:\> Get-MdcaAlert -ID 909cd095-1677-44eb-98a3-dda1e3c26733 Retrieve the specified alert #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'identity', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias('_id')] [string[]] $ID, [Parameter(ParameterSetName = 'default')] [Parameter(ParameterSetName = 'Filter')] [ValidateSet('date', 'severity')] [string] $SortField, [Parameter(ParameterSetName = 'default')] [Parameter(ParameterSetName = 'Filter')] [switch] $Descending, [Parameter(ParameterSetName = 'default')] [Parameter(ParameterSetName = 'Filter')] [int] $Skip, [Parameter(ParameterSetName = 'default')] [Parameter(ParameterSetName = 'Filter')] [int] $Limit, [Parameter(ParameterSetName = 'Filter')] [hashtable] $Filter ) begin { Assert-DefenderAPIConnection -Service MDCA -Cmdlet $PSCmdlet } process { #region ID if ($ID) { foreach ($idString in $ID) { try { Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Path "alerts/$idString" -ErrorAction Stop } catch { $PSCmdlet.WriteError($_) } } return } #endregion ID $body = @{ } if ($SortField) { $body.sortField = $SortField $body.sortDirection = 'asc' if ($Descending) { $body.sortDirection = 'dsc' } } $noPaging = $false if ($PSBoundParameters.ContainsKey("Skip")) { $body.skip = $Skip; $noPaging = $true } if ($PSBoundParameters.ContainsKey("Limit")) { $body.limit = $Limit; $noPaging = $true } if ($Filter) { $body.filters = $Filter } do { $result = Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Path alerts -Body $body -Raw $body.skip = @($result.data).Count + $body.skip $result.data } while ($result.hasNext -and -not $noPaging) } } function Get-MdcaFile { <# .SYNOPSIS List or retrieve files. .DESCRIPTION List or retrieve files. .PARAMETER ID ID of the file to retrieve. .PARAMETER Skip Skip the first X results when listing files. .PARAMETER Limit Maximum number of files to retrieve. .PARAMETER Filter A custom filter as defined here: https://learn.microsoft.com/en-us/defender-cloud-apps/api-files#filters Example filter for public documents: @{ fileType = @{ eq = 1 } sharing = @{ eq = 3 } } .EXAMPLE PS C:\> Get-MdcaFile List all files. .EXAMPLE PS C:\> Get-MdcaFile -ID 25e86014-b08d-4d42-a685-ca00a230c458 Retrieve the specified file. #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'identity', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias('_id')] [string[]] $ID, [Parameter(ParameterSetName = 'default')] [int] $Skip, [Parameter(ParameterSetName = 'default')] [int] $Limit, [hashtable] $Filter ) begin { Assert-DefenderAPIConnection -Service MDCA -Cmdlet $PSCmdlet } process { #region ID if ($ID) { foreach ($idString in $ID) { try { Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Path "files/$idString" -ErrorAction Stop } catch { $PSCmdlet.WriteError($_) } } return } #endregion ID $body = @{ } $noPaging = $false if ($PSBoundParameters.ContainsKey("Skip")) { $body.skip = $Skip; $noPaging = $true } if ($PSBoundParameters.ContainsKey("Limit")) { $body.limit = $Limit; $noPaging = $true } if ($Filter) { $body.filters = $Filter } do { $result = Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Path files -Body $body -Raw $body.skip = @($result.data).Count + $body.skip $result.data } while ($result.hasNext -and -not $noPaging) } } function Get-MdcaSubnet { <# .SYNOPSIS Returns the available / configured subnets. .DESCRIPTION Returns the available / configured subnets. Note: Filter parameters are currently non-functional. .PARAMETER ID ID of a subnet to retrieve. .PARAMETER SortField Field by which to sort the results. .PARAMETER Descending Whether to sort in a descending order .PARAMETER Skip Skip the first X results Using this parameter disables the automatic paging feature. .PARAMETER Limit Maximum number of subnets to return. Using this parameter disables the automatic paging feature. .PARAMETER Filter A full filter to specify with the request .PARAMETER IncludeCategory Only return subnets that contain any of the specified categories. .PARAMETER ExcludeCategory Do not return subnets that contain any of the specified categories. .PARAMETER IncludeTag Only return subnets that contain any of the specified tags. .PARAMETER ExcludeTag Do not return subnets that contain any of the specified tags. .PARAMETER BuiltIn Specify whether built-in only or custom only subnets should be returned .EXAMPLE PS C:\> Get-MdcaSubnet Returns all subnets from MDCA #> [CmdletBinding(DefaultParameterSetName = 'default')] Param ( [Parameter(Mandatory = $true, ParameterSetName = 'identity', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias('_id')] [string[]] $ID, [ValidateSet('category', 'tags', 'name')] [string] $SortField, [switch] $Descending, [int] $Skip, [int] $Limit, [Parameter(ParameterSetName = 'Filter')] [hashtable] $Filter, [Parameter(ParameterSetName = 'Condition')] [SubnetCategory[]] $IncludeCategory, [Parameter(ParameterSetName = 'Condition')] [SubnetCategory[]] $ExcludeCategory, [Parameter(ParameterSetName = 'Condition')] [string[]] $IncludeTag, [Parameter(ParameterSetName = 'Condition')] [string[]] $ExcludeTag, [Parameter(ParameterSetName = 'Condition')] [bool] $BuiltIn ) begin { Assert-DefenderAPIConnection -Service MDCA -Cmdlet $PSCmdlet } process { if ($ID) { foreach ($idString in $ID) { try { Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Path "subnet/$idString" -ErrorAction Stop | ConvertFrom-RestSubnet } catch { $PSCmdlet.WriteError($_) } } return } $body = @{ } if ($SortField) { $body.sortField = $SortField $body.sortDirection = 'asc' if ($Descending) { $body.sortDirection = 'dsc' } } $noPaging = $false if ($PSBoundParameters.ContainsKey("Skip")) { $body.skip = $Skip; $noPaging = $true } if ($PSBoundParameters.ContainsKey("Limit")) { $body.limit = $Limit; $noPaging = $true } #region Filters # TODO: Figure out why filters are ignored switch ($PSCmdlet.ParameterSetName) { 'Filter' { $body.filters = $Filter } 'Condition' { $filterHash = @{} if ($IncludeCategory -or $ExcludeCategory) { $filterHash.category = @{} if ($IncludeCategory) { $filterHash.category.eq = @($IncludeCategory | ForEach-Object { [int]$_ }) } if ($ExcludeCategory) { $filterHash.category.neq = @($ExcludeCategory | ForEach-Object { [int]$_ }) } } if ($IncludeTag -or $ExcludeTag) { $filterHash.tags = @{ } if ($IncludeTag) { $filterHash.tags.eq = $IncludeTag } if ($ExcludeTag) { $filterHash.tags.neq = $ExcludeTag } } if ($PSBoundParameters.ContainsKey("BuiltIn")) { $filterHash.builtIn = @{ eq = $BuiltIn } } $body.filters = $filterHash } } #endregion Filters do { $result = Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Path 'subnet/' -Body $body -Raw $body.skip = @($result.data).Count + $body.skip $result.data | ConvertFrom-RestSubnet } while ($result.hasNext -and -not $noPaging) } } function New-MdcaSubnet { <# .SYNOPSIS Create a new MDCA subnet .DESCRIPTION Create a new MDCA subnet .PARAMETER Name Name of the subnet to create .PARAMETER Category The category the subnet should have .PARAMETER Subnets IPRanges / subnets that should be part of this subnet .PARAMETER Organization The organization this subnet is part of .PARAMETER Tag Any tags this subnet should have. .PARAMETER EnableException This parameters disables user-friendly warnings and enables the throwing of exceptions. This is less user friendly, but allows catching exceptions in calling scripts. .PARAMETER WhatIf if this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> New-MdcaSubnet -Name "europe" -Category Corporate -Subnets '10.1.0.0/16' -Organization ContosoEU -Tag europe, intranet Creates a new MDCA subnet #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','')] [CmdletBinding(SupportsShouldProcess = $true)] Param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $Name, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [SubnetCategory] $Category, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string[]] $Subnets, [Parameter(ValueFromPipelineByPropertyName = $true)] [string] $Organization, [Parameter(ValueFromPipelineByPropertyName = $true)] [Alias('tags')] [string[]] $Tag, [switch] $EnableException ) begin { Assert-DefenderAPIConnection -Service MDCA -Cmdlet $PSCmdlet } process { $body = @{ name = $Name category = [int]$Category subnets = $Subnets } if ($Organization) { $body.organization = $Organization } if ($Tag) { $body.tags = $Tag } Invoke-PSFProtectedCommand -ActionString 'New-MdcaSubnet.Create' -ActionStringValues $Name -Target $Name -ScriptBlock { $newID = Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Method Post -Path "subnet/create_rule/" -Body $body } -EnableException $EnableException -PSCmdlet $PSCmdlet Get-MdcaSubnet -ID $newID } } function Remove-MdcaSubnet { <# .SYNOPSIS Remove a MDCA subnet .DESCRIPTION Remove a MDCA subnet .PARAMETER ID ID of the subnet to remove .PARAMETER EnableException This parameters disables user-friendly warnings and enables the throwing of exceptions. This is less user friendly, but allows catching exceptions in calling scripts. .PARAMETER WhatIf if this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Get-MdcaSubnet | Where-Object Name -eq na | Remove-MdcaSubnet Removes the subnet named "na" #> [CmdletBinding(SupportsShouldProcess = $true)] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias('_id')] [string[]] $ID, [switch] $EnableException ) begin { Assert-DefenderAPIConnection -Service MDCA -Cmdlet $PSCmdlet } process { foreach ($subnetID in $ID) { Invoke-PSFProtectedCommand -ActionString 'Remove-MdcaSubnet.Deleting' -ActionStringValues $subnetID -Target $subnetID -ScriptBlock { $null = Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Method Delete -Path "subnet/$subnetID" -ErrorAction Stop } -EnableException $EnableException -Continue -PSCmdlet $PSCmdlet } } } function Set-MdcaSubnet { <# .SYNOPSIS Updates an existing MDCA subnet. .DESCRIPTION Updates an existing MDCA subnet. All properties will be overwritten each time! Not specifying tags equals to removing all existing tags. Note: Each time you update a subnet you must change its name. .PARAMETER ID ID of the subnet to modify. .PARAMETER Name The name to assign to the subnet. Note: Each time you update a subnet you must change its name. .PARAMETER Category The category the subnet should have. .PARAMETER Subnets The IP ranges assigned to this subnet .PARAMETER Organization The Organization the subnet is part of .PARAMETER Tag Any tags the subnet should include .PARAMETER PassThru Whether the result should be returned as output .PARAMETER EnableException This parameters disables user-friendly warnings and enables the throwing of exceptions. This is less user friendly, but allows catching exceptions in calling scripts. .PARAMETER WhatIf if this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Get-MdcaSubnet | Where-Object Name -match "^na_{0,1}$" | Set-MdcaSubnet -Subnets '66.66.66.0/24' -Name { ($_.Name + "_") -replace "__" } Updates the subnet na to _only_ include the iprange '66.66.66.0/24'. Alternates the name between "na" and "na_" #> [CmdletBinding(SupportsShouldProcess = $true)] Param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('_id')] [string] $ID, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $Name, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [SubnetCategory] $Category, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string[]] $Subnets, [Parameter(ValueFromPipelineByPropertyName = $true)] [string] $Organization, [Parameter(ValueFromPipelineByPropertyName = $true)] [Alias('tags')] [string[]] $Tag, [switch] $PassThru, [switch] $EnableException ) begin { Assert-DefenderAPIConnection -Service MDCA -Cmdlet $PSCmdlet } process { try { $subnet = Get-MdcaSubnet -ID $ID -ErrorAction Stop } catch { Stop-PSFFunction -String 'Set-MdcaSubnet.NotFound' -StringValues $ID -EnableException $EnableException return } if ($subnet.name -eq $Name) { Stop-PSFFunction -String 'Set-MdcaSubnet.DuplicateName' -StringValues $ID, $Name, $subnet.name -EnableException $EnableException return } $body = @{ name = $Name category = [int]$Category subnets = $Subnets } if ($Organization) { $body.organization = $Organization } if ($Tag) { $body.tags = $Tag } Invoke-PSFProtectedCommand -ActionString 'Set-MdcaSubnet.Modify' -ActionStringValues $subnet.name, $Name -Target $ID -ScriptBlock { $null = Invoke-EntraRequest -Service 'DefenderAPI.MDCA' -Method Post -Path "subnet/$ID/update_rule/" -Body $body } -EnableException $EnableException -PSCmdlet $PSCmdlet if ($PassThru) { Get-MdcaSubnet -ID $ID } } } function Invoke-MdAdvancedQuery { <# .SYNOPSIS Advanced Hunting .DESCRIPTION Run a custom query in Windows Defender ATP Scopes required (delegate auth): AdvancedQuery.Read .PARAMETER Query The query to run .EXAMPLE PS C:\> Invoke-MdAdvancedQuery -Query $query Run a custom query in Windows Defender ATP .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/run-advanced-query-api?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Query ) process { $__mapping = @{ 'Query' = 'Query' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Query') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'advancedqueries/run' Method = 'post' RequiredScopes = 'AdvancedQuery.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param | ConvertFrom-AdvancedQuery } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdAdvancedQuerySchema { <# .SYNOPSIS Advanced Hunting Schema .DESCRIPTION Gets the schema for a Windows Defender ATP custom query .PARAMETER Query The query to run .EXAMPLE PS C:\> Set-MdAdvancedQuerySchema -Query $query Gets the schema for a Windows Defender ATP custom query .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Query ) process { $__mapping = @{ 'Query' = 'Query' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Query') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'advancedqueries/schema' Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdAlert { <# .SYNOPSIS Alerts - Get list of alerts .DESCRIPTION Retrieve from Windows Defender ATP the most recent alerts Scopes required (delegate auth): Alert.Read .PARAMETER Top Returns only the first n results. .PARAMETER Orderby Sorts the results. .PARAMETER Select Selects which properties to include in the response, defaults to all. .PARAMETER Filter Filters the results, using OData syntax. .PARAMETER AlertID The identifier of the alert to retrieve .PARAMETER Expand Expands related entities inline. .PARAMETER Count Includes a count of the matching results in the response. .PARAMETER Skip Skips the first n results. .EXAMPLE PS C:\> Get-MdAlert -AlertID $alertid Retrieve from Windows Defender ATP a specific alert .EXAMPLE PS C:\> Get-MdAlert Retrieve from Windows Defender ATP the most recent alerts .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-alerts?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Top, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Orderby, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string[]] $Select, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Filter, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'GetSingleAlert')] [string] $AlertID, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Expand, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [boolean] $Count, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Skip ) process { $__mapping = @{ 'Top' = '$top' 'Orderby' = '$orderby' 'Select' = '$select' 'Filter' = '$filter' 'Expand' = '$expand' 'Count' = '$count' 'Skip' = '$skip' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @('Top','Orderby','Select','Filter','Expand','Count','Skip') -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'alerts' Method = 'get' RequiredScopes = 'Alert.Read' Service = 'DefenderAPI.Endpoint' } if ($AlertID) { $__param.Path += "/$AlertID" } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function New-MdAlert { <# .SYNOPSIS Alerts - Create alert .DESCRIPTION Create Alert based on specific Event Scopes required (delegate auth): Alert.ReadWrite .PARAMETER ReportID Report Id of the event .PARAMETER EventTime Time of the event as string, e.g. 2018-08-03T16:45:21.7115183Z .PARAMETER MachineID ID of the machine on which the event was identified .PARAMETER RecommendedAction Recommended action for the Alert .PARAMETER Title Title of the Alert .PARAMETER Category Category of the alert .PARAMETER Severity Severity of the alert. .PARAMETER Description Description of the Alert .EXAMPLE PS C:\> New-MdAlert -Title $title -Category $category -Severity $severity -Description $description Create Alert based on specific Event .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/create-alert-by-reference?view=o365-worldwide #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $ReportID, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $EventTime, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $MachineID, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $RecommendedAction, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Title, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Category, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Severity, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Description ) process { $__mapping = @{ 'ReportID' = 'Report ID' 'EventTime' = 'Event Time' 'MachineID' = 'Machine ID' 'RecommendedAction' = 'Recommended Action' 'Title' = 'Title' 'Category' = 'Category' 'Severity' = 'Severity' 'Description' = 'Description' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('ReportID','EventTime','MachineID','RecommendedAction','Title','Category','Severity','Description') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'alerts/createAlertByReference' Method = 'post' RequiredScopes = 'Alert.ReadWrite' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdAlert { <# .SYNOPSIS Alerts - Update alert .DESCRIPTION Update a Windows Defender ATP alert Scopes required (delegate auth): Alert.ReadWrite .PARAMETER Comment A comment to associate to the alert .PARAMETER AssignedTo Person to assign the alert to .PARAMETER Status Status of the alert. One of 'New', 'InProgress' and 'Resolved' .PARAMETER Classification Classification of the alert. One of 'Unknown', 'FalsePositive', 'TruePositive' .PARAMETER AlertID The identifier of the alert to update .PARAMETER Determination The determination of the alert. One of 'NotAvailable', 'Apt', 'Malware', 'SecurityPersonnel', 'SecurityTesting', 'UnwantedSoftware', 'Other' .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .EXAMPLE PS C:\> Set-MdAlert -AlertID $alertid Update a Windows Defender ATP alert .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/update-alert?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default', SupportsShouldProcess = $true)] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $AssignedTo, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Status, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Classification, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $AlertID, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Determination ) process { $__mapping = @{ 'Comment' = 'Comment' 'AssignedTo' = 'Assigned to' 'Status' = 'Status' 'Classification' = 'Classification' 'Determination' = 'Determination' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment','AssignedTo','Status','Classification','Determination') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'alerts/{AlertID}' -Replace '{AlertID}',$AlertID Method = 'patch' RequiredScopes = 'Alert.ReadWrite' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' if (-not $PSCmdlet.ShouldProcess("$AlertID","Update existing Alert")) { return } try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdDeviceSecureScore { <# .SYNOPSIS Retrieves your Microsoft Secure Score for Devices .DESCRIPTION Retrieves your Microsoft Secure Score for Devices. A higher Microsoft Secure Score for Devices means your endpoints are more resilient from cybersecurity threat attacks. Scopes required (delegate auth): Score.Read .EXAMPLE PS C:\> Get-MdDeviceSecureScore <insert description here> .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-device-secure-score?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'configurationScore' Method = 'get' RequiredScopes = 'Score.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdExposureScore { <# .SYNOPSIS Retrieves the organizational exposure score. .DESCRIPTION Retrieves the organizational exposure score. Scopes required (delegate auth): Score.Read .EXAMPLE PS C:\> Get-MdExposureScore <insert description here> .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-exposure-score?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'exposureScore' Method = 'get' RequiredScopes = 'Score.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdMachineGroupExposureScore { <# .SYNOPSIS Retrieves a collection of alerts related to a given domain address. .DESCRIPTION Retrieves a collection of alerts related to a given domain address. Scopes required (delegate auth): Score.Read .EXAMPLE PS C:\> Get-MdMachineGroupExposureScore <insert description here> .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machine-group-exposure-score?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'exposureScore/byMachineGroups' Method = 'get' RequiredScopes = 'Score.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdFile { <# .SYNOPSIS Files - Get a single file .DESCRIPTION Retrieve from Windows Defender ATP a specific file by identifier Sha1, or Sha256 .PARAMETER FileID The file identifier - Sha1, or Sha256 .EXAMPLE PS C:\> Get-MdFile -FileID $fileid Retrieve from Windows Defender ATP a specific file by identifier Sha1, or Sha256 .LINK <unknown> #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $FileID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'files/{FileID}' -Replace '{FileID}',$FileID Method = 'get' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdFileAlert { <# .SYNOPSIS Files - Get alerts related to a file .DESCRIPTION Retrieve from Windows Defender ATP a collection of alerts related to a given file by identifier Sha1, or Sha256 .PARAMETER FileID The file identifier - Sha1, or Sha256 .EXAMPLE PS C:\> Get-MdFileAlert -FileID $fileid Retrieve from Windows Defender ATP a collection of alerts related to a given file by identifier Sha1, or Sha256 .LINK <unknown> #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $FileID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'files/{FileID}/alerts' -Replace '{FileID}',$FileID Method = 'get' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdFileMachine { <# .SYNOPSIS Files - Get machines related to a file .DESCRIPTION Retrieve from Windows Defender ATP a collection of machines related to a given file by identifier Sha1, or Sha256 .PARAMETER FileID The file identifier - Sha1, or Sha256 .EXAMPLE PS C:\> Get-MdFileMachine -FileID $fileid Retrieve from Windows Defender ATP a collection of machines related to a given file by identifier Sha1, or Sha256 .LINK <unknown> #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $FileID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'files/{FileID}/machines' -Replace '{FileID}',$FileID Method = 'get' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdIndicator { <# .SYNOPSIS Indicators - Get list of all active indicators .DESCRIPTION Retrieve from Windows Defender ATP list of all active indicators .PARAMETER Top Returns only the first n results. .PARAMETER Orderby Sorts the results. .PARAMETER Select Selects which properties to include in the response, defaults to all. .PARAMETER Filter Filters the results, using OData syntax. .PARAMETER Count Includes a count of the matching results in the response. .PARAMETER Skip Skips the first n results. .EXAMPLE PS C:\> Get-MdIndicator Retrieve from Windows Defender ATP list of all active indicators .LINK <unknown> #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Top, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Orderby, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string[]] $Select, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Filter, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [boolean] $Count, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Skip ) process { $__mapping = @{ 'Top' = '$top' 'Orderby' = '$orderby' 'Select' = '$select' 'Filter' = '$filter' 'Count' = '$count' 'Skip' = '$skip' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @('Top','Orderby','Select','Filter','Count','Skip') -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'indicators' Method = 'get' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function New-MdIndicator { <# .SYNOPSIS Indicators - Submit a new indicator .DESCRIPTION Submit a new indicator Scopes required (delegate auth): Ti.ReadWrite .PARAMETER IndicatorType The type of the indicator .PARAMETER Title The indicator title .PARAMETER ExpirationTime The expiration time of the indicator .PARAMETER Application The application associated with the indicator .PARAMETER Severity The severity of the indicator .PARAMETER RecommendedActions Recommended actions for the indicator .PARAMETER IndicatorValue The value of the indicator .PARAMETER Description The indicator description .PARAMETER Action The action that will be taken if the indicator will be discovered in the organization .EXAMPLE PS C:\> New-MdIndicator -Title $title -Description $description -Action $action Submit a new indicator .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/post-ti-indicator?view=o365-worldwide #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $IndicatorType, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Title, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $ExpirationTime, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Application, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Severity, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $RecommendedActions, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $IndicatorValue, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Description, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Action ) process { $__mapping = @{ 'IndicatorType' = 'Indicator type' 'Title' = 'Title' 'ExpirationTime' = 'Expiration time' 'Application' = 'Application' 'Severity' = 'Severity' 'RecommendedActions' = 'Recommended Actions' 'IndicatorValue' = 'Indicator Value' 'Description' = 'Description' 'Action' = 'Action' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('IndicatorType','Title','ExpirationTime','Application','Severity','RecommendedActions','IndicatorValue','Description','Action') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'indicators' Method = 'post' RequiredScopes = 'Ti.ReadWrite' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Remove-MdIndicator { <# .SYNOPSIS Indicators - Delete a single indicator by id .DESCRIPTION Delete a single indicator by indicator id .PARAMETER IndicatorID The identifier of the Indicator to delete .EXAMPLE PS C:\> Remove-MdIndicator -IndicatorID $indicatorid Delete a single indicator by indicator id .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $IndicatorID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'indicators/{IndicatorID}' -Replace '{IndicatorID}',$IndicatorID Method = 'delete' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdInvestigation { <# .SYNOPSIS Actions - Get list of investigation .DESCRIPTION Retrieve from Microsoft Defender ATP the most recent investigations .PARAMETER Top Returns only the first n results. .PARAMETER Orderby Sorts the results. .PARAMETER Select Selects which properties to include in the response, defaults to all. .PARAMETER Filter Filters the results, using OData syntax. .PARAMETER Count Includes a count of the matching results in the response. .PARAMETER InvestigationID The identifier of the investigation to retrieve .PARAMETER Skip Skips the first n results. .EXAMPLE PS C:\> Get-MdInvestigation -InvestigationID $investigationid Retrieve from Microsoft Defender ATP a specific investigation .EXAMPLE PS C:\> Get-MdInvestigation Retrieve from Microsoft Defender ATP the most recent investigations .LINK <unknown> #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Top, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Orderby, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string[]] $Select, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Filter, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [boolean] $Count, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'GetSingleInvestigation')] [string] $InvestigationID, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Skip ) process { $__mapping = @{ 'Top' = '$top' 'Orderby' = '$orderby' 'Select' = '$select' 'Filter' = '$filter' 'Count' = '$count' 'Skip' = '$skip' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @('Top','Orderby','Select','Filter','Count','Skip') -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'investigations' Method = 'get' Service = 'DefenderAPI.Endpoint' } if ($InvestigationID) { $__param.Path += "/$InvestigationID" } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdLiveResponseResultDownloadLink { <# .SYNOPSIS Retrieves a specific live response command result by its index. .DESCRIPTION Retrieves a specific live response command result by its index. Scopes required (delegate auth): Machine.LiveResponse .PARAMETER MachineActionID The identifier of the machine action .PARAMETER CommandIndex The index of the live response command to get the results download URI for .EXAMPLE PS C:\> Get-MdLiveResponseResultDownloadLink -MachineActionID $machineactionid -CommandIndex $commandindex Get result download URI for a completed live response command .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-live-response-result?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $MachineActionID, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $CommandIndex ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machineactions/{MachineActionID}/GetLiveResponseResultDownloadLink(index={CommandIndex})' -Replace '{MachineActionID}',$MachineActionID -Replace '{CommandIndex}',$CommandIndex Method = 'get' RequiredScopes = 'Machine.LiveResponse' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdMachineAction { <# .SYNOPSIS Actions - Get list of machine actions .DESCRIPTION Retrieve from Windows Defender ATP the most recent machine actions Scopes required (delegate auth): Machine.Read .PARAMETER Top Returns only the first n results. .PARAMETER Orderby Sorts the results. .PARAMETER Select Selects which properties to include in the response, defaults to all. .PARAMETER Filter Filters the results, using OData syntax. .PARAMETER MachineActionID The identifier of the machine action to retrieve .PARAMETER Count Includes a count of the matching results in the response. .PARAMETER Skip Skips the first n results. .EXAMPLE PS C:\> Get-MdMachineAction -MachineActionID $machineactionid Retrieve from Windows Defender ATP a specific machine action .EXAMPLE PS C:\> Get-MdMachineAction Retrieve from Windows Defender ATP the most recent machine actions .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machineaction-object?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Top, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Orderby, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string[]] $Select, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Filter, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'GetSingleMachineAction')] [string] $MachineActionID, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [boolean] $Count, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Skip ) process { $__mapping = @{ 'Top' = '$top' 'Orderby' = '$orderby' 'Select' = '$select' 'Filter' = '$filter' 'Count' = '$count' 'Skip' = '$skip' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @('Top','Orderby','Select','Filter','Count','Skip') -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machineactions' Method = 'get' RequiredScopes = 'Machine.Read' Service = 'DefenderAPI.Endpoint' } if ($MachineActionID) { $__param.Path += "/$MachineActionID" } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdMachineactionGetpackageuri { <# .SYNOPSIS Actions - Get investigation package download URI .DESCRIPTION Get a URI that allows downloading of an investigation package .PARAMETER MachineactionID The ID of the investigation package collection .EXAMPLE PS C:\> Get-MdMachineactionGetpackageuri -MachineactionID $machineactionid Get a URI that allows downloading of an investigation package .LINK <unknown> #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $MachineactionID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machineactions/{MachineactionID}/getPackageUri' -Replace '{MachineactionID}',$MachineactionID Method = 'get' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineactionCancel { <# .SYNOPSIS Actions - Cancel a single machine action .DESCRIPTION Cancel a specific machine action .PARAMETER MachineActionID The identifier of the machine action to cancel .PARAMETER Comment A comment to associate to the machine action cancellation .EXAMPLE PS C:\> Set-MdMachineactionCancel -MachineActionID $machineactionid -Comment $comment Cancel a specific machine action .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $MachineActionID, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment ) process { $__mapping = @{ 'Comment' = 'Comment' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machineactions/{MachineActionID}/cancel' -Replace '{MachineActionID}',$MachineActionID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Disable-MdMachineIsolation { <# .SYNOPSIS Undo isolation of a device. .DESCRIPTION Undo isolation of a device. Scopes required (delegate auth): Machine.Isolate .PARAMETER Comment A comment to associate to the unisolation .PARAMETER MachineID The ID of the machine to unisolate .EXAMPLE PS C:\> Disable-MdMachineIsolation -Comment $comment -MachineID $machineid Unisolate a machine from network .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/unisolate-machine?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/unisolate' -Replace '{MachineID}',$MachineID Method = 'post' RequiredScopes = 'Machine.Isolate' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Enable-MdMachineIsolation { <# .SYNOPSIS Isolates a device from accessing external network. .DESCRIPTION Isolates a device from accessing external network. Scopes required (delegate auth): Machine.Isolate .PARAMETER Comment A comment to associate to the isolation .PARAMETER IsolationType Type of the isolation. Allowed values are 'Full' (for full isolation) or 'Selective' (to restrict only limited set of applications from accessing the network) .PARAMETER MachineID The ID of the machine to isolate .EXAMPLE PS C:\> Enable-MdMachineIsolation -Comment $comment -MachineID $machineid Isolate a machine from network .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/isolate-machine?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $IsolationType, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' 'IsolationType' = 'Isolation Type' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment','IsolationType') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/isolate' -Replace '{MachineID}',$MachineID Method = 'post' RequiredScopes = 'Machine.Isolate' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdMachine { <# .SYNOPSIS Machines - Get list of machines .DESCRIPTION Retrieve from Windows Defender ATP the most recent machines Scopes required (delegate auth): Machine.Read .PARAMETER Top Returns only the first n results. .PARAMETER Orderby Sorts the results. .PARAMETER Select Selects which properties to include in the response, defaults to all. .PARAMETER Filter Filters the results, using OData syntax. .PARAMETER Count Includes a count of the matching results in the response. .PARAMETER MachineID The identifier of the machine to retrieve .PARAMETER Skip Skips the first n results. .EXAMPLE PS C:\> Get-MdMachine -MachineID $machineid Retrieve from Windows Defender ATP a specific machine .EXAMPLE PS C:\> Get-MdMachine Retrieve from Windows Defender ATP the most recent machines .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machines?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Top, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Orderby, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string[]] $Select, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Filter, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [boolean] $Count, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'GetSingleMachine')] [Alias('Id')] [string] $MachineID, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [int32] $Skip ) process { $__mapping = @{ 'Top' = '$top' 'Orderby' = '$orderby' 'Select' = '$select' 'Filter' = '$filter' 'Count' = '$count' 'Skip' = '$skip' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @('Top','Orderby','Select','Filter','Count','Skip') -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines' Method = 'get' RequiredScopes = 'Machine.Read' Service = 'DefenderAPI.Endpoint' } if ($MachineID) { $__param.Path += "/$MachineID" } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdMachineRecommendation { <# .SYNOPSIS Retrieves a collection of security recommendations related to a given device ID. .DESCRIPTION Retrieves a collection of security recommendations related to a given device ID. Scopes required (delegate auth): SecurityRecommendation.Read .PARAMETER MachineID ID of the machine to get recommendations for. .EXAMPLE PS C:\> Get-MdMachineRecommendation -MachineID $machineid Retrieves a collection of security recommendations related to the specified device ID. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-security-recommendations?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/recommendations' -Replace '{MachineID}',$MachineID Method = 'get' RequiredScopes = 'SecurityRecommendation.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdMachineSoftware { <# .SYNOPSIS Retrieves a collection of installed software related to a given device ID. .DESCRIPTION Retrieves a collection of installed software related to a given device ID. Scopes required (delegate auth): Software.Read .PARAMETER MachineID ID of the machine to read the installed software from. .EXAMPLE PS C:\> Get-MdMachineSoftware -MachineID $machineid <insert description here> .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-installed-software?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/software' -Replace '{MachineID}',$MachineID Method = 'get' RequiredScopes = 'Software.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdMachineVulnerability { <# .SYNOPSIS Retrieves a collection of discovered vulnerabilities related to a given device ID. .DESCRIPTION Retrieves a collection of discovered vulnerabilities related to a given device ID. Scopes required (delegate auth): Vulnerability.Read .PARAMETER MachineID ID of the machine to read the detected vulnerabilities from. .EXAMPLE PS C:\> Get-MdMachineVulnerability -MachineID $machineid <insert description here> .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-discovered-vulnerabilities?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/vulnerabilities' -Replace '{MachineID}',$MachineID Method = 'get' RequiredScopes = 'Vulnerability.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineCollectinvestigationpackage { <# .SYNOPSIS Actions - Collect investigation package .DESCRIPTION Collect investigation package from a machine .PARAMETER Comment A comment to associate to the collection .PARAMETER MachineID The ID of the machine to collect the investigation from .EXAMPLE PS C:\> Set-MdMachineCollectinvestigationpackage -Comment $comment -MachineID $machineid Collect investigation package from a machine .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/collectInvestigationPackage' -Replace '{MachineID}',$MachineID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineOffboard { <# .SYNOPSIS Actions - Offboard machine from Microsoft Defender ATP .DESCRIPTION Offboard machine from Microsoft Defender ATP .PARAMETER Comment A comment to associate to the offboarding action .PARAMETER MachineID The ID of the machine to offboard .EXAMPLE PS C:\> Set-MdMachineOffboard -Comment $comment -MachineID $machineid Offboard machine from Microsoft Defender ATP .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/offboard' -Replace '{MachineID}',$MachineID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineRestrictcodeexecution { <# .SYNOPSIS Actions - Restrict app execution .DESCRIPTION Restrict execution of all applications on the machine except a predefined set .PARAMETER Comment A comment to associate to the restriction .PARAMETER MachineID The ID of the machine to restrict .EXAMPLE PS C:\> Set-MdMachineRestrictcodeexecution -Comment $comment -MachineID $machineid Restrict execution of all applications on the machine except a predefined set .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/restrictCodeExecution' -Replace '{MachineID}',$MachineID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineRunantivirusscan { <# .SYNOPSIS Actions - Run antivirus scan .DESCRIPTION Initiate Windows Defender Antivirus scan on a machine .PARAMETER Comment A comment to associate to the scan request .PARAMETER ScanType Type of scan to perform. Allowed values are 'Quick' or 'Full' .PARAMETER MachineID The ID of the machine to scan .EXAMPLE PS C:\> Set-MdMachineRunantivirusscan -Comment $comment -MachineID $machineid Initiate Windows Defender Antivirus scan on a machine .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $ScanType, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' 'ScanType' = 'Scan Type' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment','ScanType') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/runAntiVirusScan' -Replace '{MachineID}',$MachineID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineStartinvestigation { <# .SYNOPSIS Actions - Start automated investigation on a machine .DESCRIPTION Start automated investigation on a machine .PARAMETER Comment A comment to associate to the investigation .PARAMETER MachineID The ID of the machine to investigate .EXAMPLE PS C:\> Set-MdMachineStartinvestigation -Comment $comment -MachineID $machineid Start automated investigation on a machine .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/startInvestigation' -Replace '{MachineID}',$MachineID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineStopandquarantinefile { <# .SYNOPSIS Actions - Stop and quarantine a file .DESCRIPTION Stop execution of a file on a machine and delete it. .PARAMETER Comment A comment to associate to the restriction removal .PARAMETER MachineID The ID of the machine to unrestrict .EXAMPLE PS C:\> Set-MdMachineStopandquarantinefile -Comment $comment -MachineID $machineid Stop execution of a file on a machine and delete it. .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/StopAndQuarantineFile' -Replace '{MachineID}',$MachineID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineTag { <# .SYNOPSIS Machines - Tag machine .DESCRIPTION Add or remove a tag to/from a machine .PARAMETER Action The action to perform. Value should be one of 'Add' (to add a tag) or 'Remove' (to remove a tag) .PARAMETER Value The tag to add or remove .PARAMETER MachineID The ID of the machine to which the tag should be added or removed .EXAMPLE PS C:\> Set-MdMachineTag -Action $action -Value $value -MachineID $machineid Add or remove a tag to/from a machine .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Action, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Value, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Action' = 'Action' 'Value' = 'Value' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Action','Value') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/tags' -Replace '{MachineID}',$MachineID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Set-MdMachineUnrestrictcodeexecution { <# .SYNOPSIS Actions - Remove app execution restriction .DESCRIPTION Enable execution of any application on the machine .PARAMETER Comment A comment to associate to the restriction removal .PARAMETER MachineID The ID of the machine to unrestrict .EXAMPLE PS C:\> Set-MdMachineUnrestrictcodeexecution -Comment $comment -MachineID $machineid Enable execution of any application on the machine .LINK <unknown> #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/unrestrictCodeExecution' -Replace '{MachineID}',$MachineID Method = 'post' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Start-MdMachineLiveResponse { <# .SYNOPSIS Runs a sequence of live response commands on a device .DESCRIPTION Runs a sequence of live response commands on a device Scopes required (delegate auth): Machine.LiveResponse .PARAMETER Comment A comment to associate to the isolation .PARAMETER Commands The live response commands to execute. Example: @{ type = "RunScript" params = @( @{ key = "ScriptName" value = "minidump.ps1" }, @{ key = "Args" value = "OfficeClickToRun" } ) } .PARAMETER MachineID ID of the machine to execute a live response script upon .EXAMPLE PS C:\> Start-MdMachineLiveResponse -Comment $comment -Commands $commands -MachineID $machineid Run live response api commands for a single machine .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/run-live-response?view=o365-worldwide #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Comment, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [array] $Commands, [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $MachineID ) process { $__mapping = @{ 'Comment' = 'Comment' 'Commands' = 'Commands' } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @('Comment','Commands') -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'machines/{MachineID}/runliveresponse' -Replace '{MachineID}',$MachineID Method = 'post' RequiredScopes = 'Machine.LiveResponse' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdRecommendation { <# .SYNOPSIS Retrieves a list of all security recommendations affecting the organization. .DESCRIPTION Retrieves a list of all security recommendations affecting the organization. Scopes required (delegate auth): SecurityRecommendation.Read .PARAMETER RecommendationID ID of the recommendation to retrieve. .EXAMPLE PS C:\> Get-MdRecommendation -RecommendationID $recommendationid <insert description here> .EXAMPLE PS C:\> Get-MdRecommendation Lists all security recommendations .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-all-recommendations?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'GetRecommendationById')] [Alias('Id')] [string] $RecommendationID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'recommendations' Method = 'get' RequiredScopes = 'SecurityRecommendation.Read' Service = 'DefenderAPI.Endpoint' } if ($RecommendationID) { $__param.Path += "/$RecommendationID" } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdRecommendationMachineReference { <# .SYNOPSIS Retrieves a list of devices associated with the security recommendation. .DESCRIPTION Retrieves a list of devices associated with the security recommendation. Scopes required (delegate auth): SecurityRecommendation.Read .PARAMETER RecommendationID ID of the recommendation for which to retrieve devices. .EXAMPLE PS C:\> Get-MdRecommendationMachineReference -RecommendationID $recommendationid Retrieves a list of devices associated with the security recommendation. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-recommendation-machines?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $RecommendationID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'recommendations/{RecommendationID}/machineReferences' -Replace '{RecommendationID}',$RecommendationID Method = 'get' RequiredScopes = 'SecurityRecommendation.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdRecommendationSoftware { <# .SYNOPSIS Retrieves a security recommendation related to a specific software. .DESCRIPTION Retrieves a security recommendation related to a specific software. Scopes required (delegate auth): SecurityRecommendation.Read .PARAMETER RecommendationID ID of the recommendation for which to retrieve software information. .EXAMPLE PS C:\> Get-MdRecommendationSoftware -RecommendationID $recommendationid Retrieves a security recommendation related to a specific software. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/list-recommendation-software?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $RecommendationID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'recommendations/{RecommendationID}/software' -Replace '{RecommendationID}',$RecommendationID Method = 'get' RequiredScopes = 'SecurityRecommendation.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdRecommendationVulnerability { <# .SYNOPSIS Retrieves a list of vulnerabilities associated with the security recommendation. .DESCRIPTION Retrieves a list of vulnerabilities associated with the security recommendation. Scopes required (delegate auth): Vulnerability.Read .PARAMETER RecommendationID ID of the recommendation for which to retrieve vulnerabilities. .EXAMPLE PS C:\> Get-MdRecommendationVulnerability -RecommendationID $recommendationid Retrieves a list of vulnerabilities associated with the security recommendation. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-recommendation-vulnerabilities?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $RecommendationID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'recommendations/{RecommendationID}/vulnerabilities' -Replace '{RecommendationID}',$RecommendationID Method = 'get' RequiredScopes = 'Vulnerability.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdSoftware { <# .SYNOPSIS Retrieves the organization software inventory. .DESCRIPTION Retrieves the organization software inventory. Scopes required (delegate auth): Software.Read .PARAMETER SoftwareID ID of the software to retrieve. .EXAMPLE PS C:\> Get-MdSoftware -SoftwareID $softwareid <insert description here> .EXAMPLE PS C:\> Get-MdSoftware Lists all security recommendations .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-software?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'GetProductById')] [Alias('Id')] [string] $SoftwareID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'software' Method = 'get' RequiredScopes = 'Software.Read' Service = 'DefenderAPI.Endpoint' } if ($SoftwareID) { $__param.Path += "/$SoftwareID" } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdSoftwareDistribution { <# .SYNOPSIS Shows the distribution of versions of a software in your organization. .DESCRIPTION Shows the distribution of versions of a software in your organization. Scopes required (delegate auth): Software.Read .PARAMETER SoftwareID ID of the software for which to retrieve distribution data. .EXAMPLE PS C:\> Get-MdSoftwareDistribution -SoftwareID $softwareid Shows the distribution of versions of the specified software in your organization. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-software-ver-distribution?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $SoftwareID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'software/{SoftwareID}/distribution' -Replace '{SoftwareID}',$SoftwareID Method = 'get' RequiredScopes = 'Software.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdSoftwareMachinereference { <# .SYNOPSIS Retrieve a list of device references that has this software installed. .DESCRIPTION Retrieve a list of device references that has this software installed. Scopes required (delegate auth): Software.Read .PARAMETER SoftwareID ID of the software for which to retrieve devices that have it installed. .EXAMPLE PS C:\> Get-MdSoftwareMachinereference -SoftwareID $softwareid Retrieve a list of device references that has this software installed. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machines-by-software?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $SoftwareID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'software/{SoftwareID}/machineReferences' -Replace '{SoftwareID}',$SoftwareID Method = 'get' RequiredScopes = 'Software.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdSoftwareVulnerability { <# .SYNOPSIS Retrieve a list of vulnerabilities in the installed software. .DESCRIPTION Retrieve a list of vulnerabilities in the installed software. Scopes required (delegate auth): Vulnerability.Read .PARAMETER SoftwareID ID of the software for which to retrieve devices that have it installed. .EXAMPLE PS C:\> Get-MdSoftwareVulnerability -SoftwareID $softwareid Retrieve a list of vulnerabilities in the installed software. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-vuln-by-software?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $SoftwareID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'software/{SoftwareID}/vulnerabilities' -Replace '{SoftwareID}',$SoftwareID Method = 'get' RequiredScopes = 'Vulnerability.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdVulnerability { <# .SYNOPSIS Retrieves a list of all the vulnerabilities. .DESCRIPTION Retrieves a list of all the vulnerabilities. Scopes required (delegate auth): Vulnerability.Read .PARAMETER VulnerabilityID ID of the vulnerability to retrieve. .EXAMPLE PS C:\> Get-MdVulnerability -VulnerabilityID $vulnerabilityid <insert description here> .EXAMPLE PS C:\> Get-MdVulnerability Retrieves a list of all the vulnerabilities. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-all-vulnerabilities?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'GetVulnerability')] [Alias('Id')] [string] $VulnerabilityID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'vulnerabilities' Method = 'get' RequiredScopes = 'Vulnerability.Read' Service = 'DefenderAPI.Endpoint' } if ($VulnerabilityID) { $__param.Path += "/$VulnerabilityID" } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MdVulnerableMachine { <# .SYNOPSIS Retrieves a list of devices affected by a vulnerability. .DESCRIPTION Retrieves a list of devices affected by a vulnerability. Scopes required (delegate auth): Vulnerability.Read .PARAMETER VulnerabilityID ID of the vulnerability for which to retrieve affected devices. .EXAMPLE PS C:\> Get-MdVulnerableMachine -VulnerabilityID $vulnerabilityid Retrieves a list of devices affected by a vulnerability. .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machines-by-vulnerability?view=o365-worldwide #> [CmdletBinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [Alias('Id')] [string] $VulnerabilityID ) process { $__mapping = @{ } $__param = @{ Body = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Header = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping Path = 'vulnerabilities/{VulnerabilityID}/machineReferences' -Replace '{VulnerabilityID}',$VulnerabilityID Method = 'get' RequiredScopes = 'Vulnerability.Read' Service = 'DefenderAPI.Endpoint' } $__param += $PSBoundParameters | ConvertTo-HashTable -Include 'ErrorAction', 'WarningAction', 'Verbose' try { Invoke-EntraRequest @__param } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Invoke-MSecAdvancedHuntingQuery { <# .SYNOPSIS Execute an advanced hunting query. .DESCRIPTION Execute an advanced hunting query. Requires being connected to the "security" service. To establish a connection, use the "Connect-MdeService" command with the parameter '-Service "security"' Example: Connect-DefenderAPIService -Service security -DeviceCode -ClientID $ClientID -TenantID $TenantID Scopes required (delegate auth): AdvancedHunting.Read .PARAMETER Query The hunting query to execute. .EXAMPLE PS C:\> Invoke-MSecAdvancedHuntingQuery -Query 'DeviceProcessEvents | where InitiatingProcessFileName =~ \"powershell.exe\" | project Timestamp, FileName, InitiatingProcessFileName | order by Timestamp desc | limit 2' Executes the query, searching for the latest two powershell processes .LINK https://docs.microsoft.com/en-us/microsoft-365/security/defender/api-advanced-hunting?view=o365-worldwide #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'default')] [string] $Query ) process { $__mapping = @{ 'Query' = 'Query' } $__body = $PSBoundParameters | ConvertTo-HashTable -Include @('Query') -Mapping $__mapping $__query = $PSBoundParameters | ConvertTo-HashTable -Include @() -Mapping $__mapping $__path = 'advancedhunting/run' Invoke-EntraRequest -Service 'DefenderAPI.Security' -Path $__path -Method post -Body $__body -Query $__query -RequiredScopes 'AdvancedHunting.Read' | ConvertFrom-AdvancedQuery } } <# This is an example configuration file By default, it is enough to have a single one of them, however if you have enough configuration settings to justify having multiple copies of it, feel totally free to split them into multiple files. #> <# # Example Configuration Set-PSFConfig -Module 'DefenderAPI' -Name 'Example.Setting' -Value 10 -Initialize -Validation 'integer' -Handler { } -Description "Example configuration setting. Your module can then use the setting using 'Get-PSFConfigValue'" #> Set-PSFConfig -Module 'DefenderAPI' -Name 'Import.DoDotSource' -Value $false -Initialize -Validation 'bool' -Description "Whether the module files should be dotsourced on import. By default, the files of this module are read as string value and invoked, which is faster but worse on debugging." Set-PSFConfig -Module 'DefenderAPI' -Name 'Import.IndividualFiles' -Value $false -Initialize -Validation 'bool' -Description "Whether the module files should be imported individually. During the module build, all module code is compiled into few files, which are imported instead by default. Loading the compiled versions is faster, using the individual files is easier for debugging and testing out adjustments." <# Stored scriptblocks are available in [PsfValidateScript()] attributes. This makes it easier to centrally provide the same scriptblock multiple times, without having to maintain it in separate locations. It also prevents lengthy validation scriptblocks from making your parameter block hard to read. Set-PSFScriptblock -Name 'DefenderAPI.ScriptBlockName' -Scriptblock { } #> # Available Tokens $script:_DefenderTokens = @{} # Endpoint Configuration for Requests $script:_DefenderEndpoints = @{} $script:_strings = Get-PSFLocalizedString -Module DefenderAPI # Registers the default service configurations $endpointCfg = @{ Name = 'DefenderAPI.Endpoint' ServiceUrl = 'https://api.securitycenter.microsoft.com/api' Resource = 'https://api.securitycenter.microsoft.com' DefaultScopes = @() Header = @{ 'Content-Type' = 'application/json' } HelpUrl = 'https://learn.microsoft.com/en-us/microsoft-365/security/defender-endpoint/api/apis-intro?view=o365-worldwide' } Register-EntraService @endpointCfg $securityCfg = @{ Name = 'DefenderAPI.Security' ServiceUrl = 'https://api.security.microsoft.com/api' Resource = 'https://security.microsoft.com/mtp/' DefaultScopes = @('AdvancedHunting.Read') Header = @{ 'Content-Type' = 'application/json' } HelpUrl = 'https://learn.microsoft.com/en-us/microsoft-365/security/defender/api-create-app-web?view=o365-worldwide' } Register-EntraService @securityCfg New-PSFLicense -Product 'DefenderAPI' -Manufacturer 'Friedrich Weinmann' -ProductVersion $script:ModuleVersion -ProductType Module -Name MIT -Version "1.0.0.0" -Date (Get-Date "2024-03-11") -Text @" Copyright (c) 2024 Friedrich Weinmann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. "@ #endregion Load compiled code |