Private/Google/Get-GoogleCloudIdentityPolicies.ps1
|
# PSGuerrilla - Jim Tyler, Microsoft MVP - CC BY 4.0 # https://github.com/jimrtyler/PSGuerrilla | https://creativecommons.org/licenses/by/4.0/ # AI/LLM use: see AI-USAGE.md for required attribution function Get-GoogleCloudIdentityPolicies { <# .SYNOPSIS Collects Google Workspace setting policies from the Cloud Identity Policy API and indexes them by setting type. .DESCRIPTION policies.list (https://cloudidentity.googleapis.com/v1/policies) returns the full set of effective Workspace settings (Gmail, Drive, Chat, Meet, Calendar, security, DLP rules, service on/off, …) — the data that previously could only be "verified in the Admin Console". This is what turns those placeholder checks into real ones. IMPORTANT: the cloud-identity.policies.readonly scope is requested in its OWN token, deliberately isolated from the main Google scan token. On a tenant that has NOT granted that domain-wide-delegation scope (or hasn't enabled the Cloud Identity API), the token exchange fails with unauthorized_client — we catch that and return $null so the rest of the Google scan is unaffected and the policy-backed checks simply SKIP. (Adding the scope to the shared token set would break Google auth for every tenant that hasn't delegated it — hence the isolation.) Returns an object: { All = <all policies>; ByType = @{ '<type>' = @(policies…) }; Count = <n> }, or $null when the API is unavailable. Each policy carries setting.type (e.g. 'settings/gmail.auto_forwarding'), setting.value (the per-type value struct), and policyQuery (the OU/group it applies to). .PARAMETER ServiceAccountKeyPath Path to the service-account JSON key. .PARAMETER AdminEmail Delegated super-admin to impersonate. #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$ServiceAccountKeyPath, [Parameter(Mandatory)][string]$AdminEmail, [switch]$Quiet ) $scope = 'https://www.googleapis.com/auth/cloud-identity.policies.readonly' $token = $null try { $token = Get-GoogleAccessToken -ServiceAccountKeyPath $ServiceAccountKeyPath ` -AdminEmail $AdminEmail -Scopes @($scope) } catch { Write-Verbose "Cloud Identity Policy API unavailable (scope not delegated or API not enabled): $($_.Exception.Message)" return $null } if (-not $token) { return $null } $policies = @(Invoke-GoogleAdminApi -AccessToken $token ` -Uri 'https://cloudidentity.googleapis.com/v1/policies' ` -Paginate -ItemsProperty 'policies' -Quiet:$Quiet) # Index by bare setting type ('settings/gmail.auto_forwarding' -> 'gmail.auto_forwarding'). # A type can appear multiple times (one policy per targeted OU/group). $byType = @{} foreach ($p in $policies) { if (-not $p.setting -or -not $p.setting.type) { continue } $type = ([string]$p.setting.type) -replace '^settings/', '' if (-not $type) { continue } if (-not $byType.ContainsKey($type)) { $byType[$type] = [System.Collections.Generic.List[object]]::new() } $byType[$type].Add($p) } return [PSCustomObject]@{ All = $policies ByType = $byType Count = @($policies).Count } } function Get-GooglePolicySetting { <# .SYNOPSIS Looks up a Cloud Identity setting type and returns its value object(s). .DESCRIPTION Returns an array of setting.value objects (one per matching policy / targeted OU), or @() when the type isn't present. Checks read individual fields off these values and should SKIP when an expected field is absent — so an unexpected value shape can never produce a wrong PASS/FAIL. .PARAMETER Policies The object returned by Get-GoogleCloudIdentityPolicies (or $auditData.CloudIdentityPolicies). .PARAMETER Type The bare setting type, e.g. 'gmail.auto_forwarding'. #> [CmdletBinding()] param( $Policies, [Parameter(Mandatory)][string]$Type ) if (-not $Policies -or -not $Policies.ByType) { return @() } $list = $Policies.ByType[$Type] if (-not $list) { return @() } return @($list | ForEach-Object { $_.setting.value }) } |