GoogleChronicle.psm1

#Region './Public/Get-GCCustomers.ps1' -1

function Get-GCCustomers {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [string]$CustomerCode,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1',
        [switch]$Details
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }

    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $GetHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Accept"        = "application/json"
    }

    if ($Details) {
        if (!$CustomerCode) {
            Write-Host "Google Chronicle CustomerCode is required." -ForegroundColor Yellow
            break
        }
        $uri = "$endpoint/v1/partner/customer/getcustomer?customer_code=$CustomerCode"
        try {
            $data = Invoke-RestMethod -Method Get -Headers $GetHeader -Uri $uri
            return $data
        }
        catch {
            $err = $_.ErrorDetails.Message | ConvertFrom-Json
            return $err.error
        }
    }
    else {
        $uri = "$endpoint/v1/partner/customer/listcustomers"
        try {
            $data = Invoke-RestMethod -Method Get -Headers $GetHeader -Uri $uri
            return $data
        }
        catch {
            $err = $_.ErrorDetails.Message | ConvertFrom-Json
            return $err.error
        }
    }
}
#EndRegion './Public/Get-GCCustomers.ps1' 55
#Region './Public/Get-GCDataFeeds.ps1' -1

function Get-GCDataFeeds {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1'
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }
    
    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $GetHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Accept"        = "application/json"
    }

    $uri = "$endpoint/v1/feeds"

    try {
        $data = Invoke-RestMethod -Method Get -Headers $GetHeader -Uri $uri
    } 
    catch {
        $data = $_.ErrorDetails.Message | ConvertFrom-Json
    }
    return $data
}
#EndRegion './Public/Get-GCDataFeeds.ps1' 36
#Region './Public/Get-GCIdpMetadata.ps1' -1

function Get-GCIdPMetadata {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1',
        [Parameter(Mandatory = $true)] [string] $CustomerCode
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }

    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $PostHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Content-Type"  = "application/json"
    }

    $uri = "$endpoint/v1/partner/customer/generateidpmetadata"

    try {
        $Body = @{
            "customer_subdomain" = "$CustomerCode-$Region";
        } | ConvertTo-Json
        $data = Invoke-RestMethod -Method Post -Headers $PostHeader -Body $Body -Uri $uri -TimeoutSec 1200
        return $data
    }
    catch {
        $err = $_.ErrorDetails.Message | ConvertFrom-Json
        return $err.error
    }
}
#EndRegion './Public/Get-GCIdpMetadata.ps1' 41
#Region './Public/Get-GCRules.ps1' -1

function Get-GCRules {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1',
        [int32]$PageSize = 100
    )
    if ($PageSize -gt 1000) {
        Write-host "Page size must be less than 1,000" -ForegroundColor Yellow
        break
    }

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }

    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $GetHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Accept"        = "application/json"
    }

    $uri = "$endpoint/v2/detect/rules?page_size=$PageSize"
    $completed = $null
    $Data = @()

    while (-not $completed) {
        try {
            $reqdata = Invoke-RestMethod -Method Get -Headers $GetHeader -Uri $uri
            $data += $reqdata.rules
            if ($null -eq $reqdata.rules) {
                $completed = $true
                Write-Verbose "No results found."
                $data = @{
                    "Status"  = "error";
                    "Comment" = "No detections found";
                }
            }
            $pagetoken = $reqdata.nextPageToken
            if ($null -eq $pagetoken) {
                $completed = $true
                Write-Verbose "No further results found."
            }
            $uri = "$endpoint/v2/detect/rules?page_size=$PageSize&page_token=$pagetoken"
        } 
        catch {
            $err = $_.ErrorDetails.Message | ConvertFrom-Json
            if ($err.error.status -eq "RESOURCE_EXHAUSTED") {
                Write-Verbose "API limit hit - sleeping for 60 seconds"
                Start-Sleep 60
            }
            else {
                $completed = $true
                return $err
                break
            }
        }
    }
    return $data
}
#EndRegion './Public/Get-GCRules.ps1' 69
#Region './Public/New-GCAuthToken.ps1' -1

function New-GCAuthToken {
    param (
        [Parameter(Mandatory = $true)] $CredFile,
        [switch] $Inline,
        [switch] $Ingestion
    )

    $ExpirationSeconds = 3600  # 1 hour in seconds
    $basedomain = "googleapis.com"
    $oauth2endpoint = "https://oauth2.googleapis.com/token"
    
    if ($Inline) {
        $Auth = $CredFile | ConvertFrom-Json
    } else {
        $Auth = gc $CredFile | ConvertFrom-Json
    }

    if ($null -eq $Auth ){
        Write-host "No auth file detected."
        break
    }

    $PrivateKeyPem = $auth.private_key
    $ServiceAccount = $auth.client_email
    if ($Ingestion) {
        $Scope = "https://www.googleapis.com/auth/malachite-ingestion"
    } else {
        $Scope = "https://www.googleapis.com/auth/chronicle-backstory"
    }

    # Convert PEM to RSAParameters and then import
    $RSACryptoServiceProvider = New-Object System.Security.Cryptography.RSACryptoServiceProvider
    $RSAPrivateKey = [System.Security.Cryptography.RSA]::Create()
    $RSAPrivateKey.ImportFromPem($PrivateKeyPem)
    $RSACryptoServiceProvider.ImportParameters($RSAPrivateKey.ExportParameters($true))
    
    # Create JWT Header
    $JwtHeader = '{"alg":"RS256","typ":"JWT"}'
    $JwtHeaderBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($JwtHeader))
    $JwtHeaderBase64UrlEncoded = $JwtHeaderBase64 -replace "/", "_" -replace "\+", "-" -replace "=", ""
    
    # Create JWT claim
    $Now = (Get-Date).ToUniversalTime()
    $NowUnixTimestamp = [Math]::Floor([decimal](Get-Date -Date $Now -UFormat "%s"))
    $ExpirationUnixTimestamp = $NowUnixTimestamp + $ExpirationSeconds
    $JwtClaimSet = @"
    {"iss":"$ServiceAccount","scope":"$Scope","aud":"$oauth2endpoint","exp":$ExpirationUnixTimestamp,"iat":$NowUnixTimestamp}
"@

    $JwtClaimSetBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($JwtClaimSet))
    $JwtClaimSetBase64UrlEncoded = $JwtClaimSetBase64 -replace "/", "_" -replace "\+", "-" -replace "=", ""
    
    # Sign the JWT
    $StringToSign = $JwtHeaderBase64UrlEncoded + "." + $JwtClaimSetBase64UrlEncoded
    $SHA256 = [System.Security.Cryptography.SHA256]::Create()
    $Hash = $SHA256.ComputeHash([Text.Encoding]::UTF8.GetBytes($StringToSign))
    $SignatureBase64 = [Convert]::ToBase64String($RSACryptoServiceProvider.SignData([System.Text.Encoding]::UTF8.GetBytes($StringToSign), "SHA256"))
    $SignatureBase64UrlEncoded = $SignatureBase64 -replace "/", "_" -replace "\+", "-" -replace "=", ""
    
    # Get Access token from Google
    $Jwt = $JwtHeaderBase64UrlEncoded + "." + $JwtClaimSetBase64UrlEncoded + "." + $SignatureBase64UrlEncoded
    $Body = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=$Jwt"
    $AccessToken = Invoke-RestMethod -Method Post -Uri "$oauth2endpoint" -ContentType "application/x-www-form-urlencoded" -Body $Body
    $at = $AccessToken.access_token
        
    $tokendata = @{
        "token"  = "$at";
        "expiry" = "$ExpirationUnixTimestamp";
        "expires_in" = "$($AccessToken.expires_in)"
    }
    return $tokendata
}
#EndRegion './Public/New-GCAuthToken.ps1' 72
#Region './Public/New-GCCustomer.ps1' -1

function New-GCCustomer {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [Parameter(Mandatory = $true)] [string] $CustomerCode,
        [Parameter(Mandatory = $true)]
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region,
        [Parameter(Mandatory = $true)] [string] $CustomerName
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }

    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $PostHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Content-Type"  = "application/json"
    }

    $uri = "$endpoint/v1/partner/customer/createcustomer"

    try {
        $Body = @{
            "customer_name" = $CustomerName;
            "customer_code" = $CustomerCode;
            "customer_subdomains" = "$CustomerCode-$Region";
        } | ConvertTo-Json
        Write-Host "This command can take upto 10 minutes to execute. Please be paitent." -ForegroundColor Yellow
        $data = Invoke-RestMethod -Method Post -Headers $PostHeader -Body $Body -Uri $uri -TimeoutSec 1200
        return $data
        Write-Host "Customer $($data.response.customerCode) created." -ForegroundColor Green
    }
    catch {
        $err = $_.ErrorDetails.Message | ConvertFrom-Json
        return $err.error
    }
}
#EndRegion './Public/New-GCCustomer.ps1' 47
#Region './Public/New-GCRule.ps1' -1

function New-GCRule {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [Parameter(Mandatory = $true)]
        $Content,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1'
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }

    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $PostHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Content-Type"  = "application/json"
    }

    $DetectionBody = @{
        "ruleText" = $Content
    } | Convertto-json

    $verifyuri = "$endpoint/v2/detect/rules:verifyRule"
    $newruleuri = "$endpoint/v2/detect/rules"

    try {
        $verify = Invoke-RestMethod -Method Post -Headers $PostHeader -Uri $verifyuri -Body $DetectionBody
        if ($verify.success -eq $true) {
            $newrule = Invoke-RestMethod -Method Post -Headers $PostHeader -Uri $newruleuri -Body $DetectionBody
            if ($newrule.compilationState -eq "SUCCEEDED") {
                $ruleid = $newrule.ruleId
                $status = @{
                    "Status"   = $newrule.compilationState;
                    "ruleName" = $newrule.ruleName;
                    "RuleId"   = $newrule.ruleId;
                }
                return $status
            }
            else {
                $status = @{
                    "Status" = "error";
                    "Error"  = $newrule.compilationState;
                }            
                return $status
            }
        }
        else {
            $status = @{
                "Status" = "error";
                "Error"  = $verify.context;
            }   
            return $status
        }
    } 
    catch {
        $data = $_.ErrorDetails.Message | ConvertFrom-Json
        return $data
    }
}
#EndRegion './Public/New-GCRule.ps1' 69
#Region './Public/New-GCRuleVersion.ps1' -1

function New-GCRuleVersion {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [Parameter(Mandatory = $true)]
        $Content,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1',
        [Parameter(Mandatory = $true)]
        [string] $RuleId
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }

    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $PostHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Content-Type"  = "application/json"
    }

    $DetectionBody = @{
        "ruleText" = $Content
    } | Convertto-json

    $verifyuri = "$endpoint/v2/detect/rules:verifyRule"
    $newruleuri = "$endpoint/v2/detect/rules/$($RuleId):createVersion"

    try {
        $verify = Invoke-RestMethod -Method Post -Headers $PostHeader -Uri $verifyuri -Body $DetectionBody
        if ($verify.success -eq $true) {
            $newrule = Invoke-RestMethod -Method Post -Headers $PostHeader -Uri $newruleuri -Body $DetectionBody
            if ($newrule.compilationState -eq "SUCCEEDED") {
                $ruleid = $newrule.ruleId
                $status = @{
                    "Status"   = $newrule.compilationState;
                    "ruleName" = $newrule.ruleName;
                    "RuleId"   = $newrule.ruleId;
                }
                return $status
            }
            else {
                $status = @{
                    "Status" = "error";
                    "Error"  = $newrule.compilationState;
                }            
                return $status
            }
        }
        else {
            $status = @{
                "Status" = "error";
                "Error"  = $verify.context;
            }   
            return $status
        }
    } 
    catch {
        $data = $_.ErrorDetails.Message | ConvertFrom-Json
        return $data
    }
}
#EndRegion './Public/New-GCRuleVersion.ps1' 71
#Region './Public/Remove-GCRule.ps1' -1

function Remove-GCRule {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [Parameter(Mandatory = $true)]
        $RuleId,
        [Parameter(Mandatory = $false)]
        [switch] $Recover,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1'
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }

    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash
    
    $PostHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Content-Type"  = "application/json"
    }

    if ($Recover) {
        $uri = "$endpoint/v2/detect/rules/$($RuleId):unarchive"       
    }
    else {
        $uri = "$endpoint/v2/detect/rules/$($RuleId):archive"       
    }

    try {
        $data = Invoke-RestMethod -Method Post -Headers $PostHeader -Uri $uri
        $status = @{
            "Status" = "successful"
            "RuleId" = $RuleId
        }
        return $status
    }
    catch {
        $err = $_.ErrorDetails.Message | ConvertFrom-Json
        return $err.error
    }
}
#EndRegion './Public/Remove-GCRule.ps1' 50
#Region './Public/Set-GCBigQueryAccess.ps1' -1

function Set-GCBigQueryAccess {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [Parameter(Mandatory = $true)]
        [string] $EmailAddress,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1'
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }
    
    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $PostHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Content-Type"  = "application/json"
    }

    $Body = @{
        "email" = $EmailAddress
    } | Convertto-json

    $uri = "$endpoint/v1/tools/bigqueryAccess:update"
    try {
        $data = Invoke-RestMethod -Method Patch -Headers $PostHeader -Uri $uri -Body $Body
        $status = @{
            "Status" = "Successful";
            "Email" = "$($data.email)";
            "Roles" = "$($data.roles.name)";
        }
        return $status
    }
    catch {
        $err = $_.ErrorDetails.Message | ConvertFrom-Json
        return $err    
    } 
}
#EndRegion './Public/Set-GCBigQueryAccess.ps1' 47
#Region './Public/Set-GCRuleConfig.ps1' -1

function Set-GCRuleConfig {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [Parameter(Mandatory = $true)]
        $RuleId,
        [Parameter(Mandatory = $false)]
        [switch] $EnableLiveRule,
        [Parameter(Mandatory = $false)]
        [switch] $DisableLiveRule,
        [Parameter(Mandatory = $false)]
        [switch] $EnableAlerting,
        [Parameter(Mandatory = $false)]
        [switch] $DisableAlerting,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1'
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }
    
    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $PostHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Content-Type"  = "application/json"
    }

    $selectedSwitches = @($EnableLiveRule, $DisableLiveRule, $EnableAlerting, $DisableAlerting) | Where-Object { $_ }    
    if ($selectedSwitches.Count -gt 1) {
        Write-Host "Select only 1 switch." -ForegroundColor Yellow
    }
    else {
        $action = switch ($selectedSwitches) {
            $EnableLiveRule { "enableLiveRule" }
            $DisableLiveRule { "disableLiveRule" }
            $EnableAlerting { "enableAlerting" }
            $DisableAlerting { "disableAlerting" }
        }
        if ($action) {
            $uri = "$endpoint/v2/detect/rules/$($RuleId):$action"
        }
        else {
            Write-Host "Invalid switch selected." -ForegroundColor Yellow
            break
        }
    }

    try {
        $data = Invoke-RestMethod -Method Post -Headers $PostHeader -Uri $uri
        $status = @{
            "Status" = "Successful";
            "RuleId" = "$RuleId";
            "Action" = $action;
        }
        return $status
    }
    catch {
        $err = $_.ErrorDetails.Message | ConvertFrom-Json
        return $err    
    } 
}
#EndRegion './Public/Set-GCRuleConfig.ps1' 70
#Region './Public/Test-GCAuthToken.ps1' -1

function Test-GCAuthToken {
    param (
        [Parameter(Mandatory = $true)] $Auth
    )

    $TokenExpiryUtc = [System.DateTimeOffset]::FromUnixTimeSeconds($Auth.expiry).UtcDateTime
    $CurrentTimeUtc = Get-Date -AsUTC

    if ($CurrentTimeUtc -le $TokenExpiryUtc) {
        $timeRemaining = ($TokenExpiryUtc - $CurrentTimeUtc).TotalMinutes
        Write-Verbose "Token is still valid. Time remaining: $($timeRemaining) minutes"
        $data = @{
            "Valid"            = $true;
            "Minutes" = $timeRemaining;
        }   
    }
    else {
        Write-Verbose "Token has expired. Please generate a new one."
        $data = @{
            "Valid"            = $false;
            "Minutes" = 0;
        }  
    }
    return $data
}
#EndRegion './Public/Test-GCAuthToken.ps1' 26
#Region './Public/Update-GCRule.ps1' -1

function Update-GCRule {
    param (
        [Parameter(Mandatory = $true)]
        $Auth,
        [Parameter(Mandatory = $true)]
        $Content,
        [Parameter(Mandatory = $true)]
        $RuleId,
        [ValidateSet('europe', 'europe-west3', 'europe-west2', 'asia-southeast1', 'australia-southeast1', 'me-west1', 'united-states', 'europe-west6')]
        [string]$Region = 'asia-southeast1'
    )

    $ts = Test-GCAuthToken -Auth $Auth
    if (($ts.valid -eq $true -and $ts.minutes -le 5)) {
        Write-Host "The auth token is near expirty. Please renew it." -ForegroundColor Yellow
        break
    }
    elseif ($ts.valid -eq $false) {
        Write-Host "Token has expired. Please renew it."
        break
    }

    $endpoint = "https://$Region-backstory.googleapis.com" # No trailing slash

    $PostHeader = @{
        "Authorization" = "Bearer $($Auth.token)";
        "Content-Type"  = "application/json"
    }

    $DetectionBody = @{
        "ruleText" = $Content
    } | Convertto-json

    $verifyuri = "$endpoint/v2/detect/rules:verifyRule"
    $newruleuri = "$endpoint/v2/detect/rules/$($RuleId):createVersion"

    try {
        $verify = Invoke-RestMethod -Method Post -Headers $PostHeader -Uri $verifyuri -Body $DetectionBody
        if ($verify.success -eq $true) {
            $newrule = Invoke-RestMethod -Method Post -Headers $PostHeader -Uri $newruleuri -Body $DetectionBody
            if ($newrule.compilationState -eq "SUCCEEDED") {
                $ruleid = $newrule.ruleId
                $status = @{
                    "Status"   = $newrule.compilationState;
                    "ruleName" = $newrule.ruleName;
                    "RuleId"   = $newrule.ruleId;
                }
                return $status
            }
            else {
                $status = @{
                    "Status" = "error";
                    "Error"  = $newrule.compilationState;
                }            
                return $status
            }
        }
        else {
            $status = @{
                "Status" = "error";
                "Error"  = $verify.context;
            }   
            return $status
        }
    }
    catch {
        $err = $_.ErrorDetails.Message | ConvertFrom-Json
        return $err    
    }
}
#EndRegion './Public/Update-GCRule.ps1' 71