GoSpace Manager

Version v0.11.0

Manage Google Workspace resources using a developer-friendly CLI written in Go

Example Script

WORD OF WARNING

This script is meant as an example. I take no responsibility if you somehow manage to break anything with it.

While you should probably be able to use the script as-is, I highly recommend that you take a look at what you need and write your own code. Again, this is meant as an example.

Also, please be aware that this script exports way more than you probably need, so don’t expect it to be fast.

Script

Note that this script uses the GSM PowerShell Module to demontrate its usage. The same functionality can be achieved without it and it is entirely optional!

param(
    [Parameter(Mandatory = $true)][String]$ExportPath,
    [Parameter(Mandatory = $true)][String]$Config,
    [Parameter(Mandatory = $false, ParameterSetName = "Single")][Switch]$UserData,
    [Parameter(Mandatory = $false, ParameterSetName = "Single")][Switch]$GroupData,
    [Parameter(Mandatory = $false, parametersetname = "Single")][Switch]$ResourceData,
    [Parameter(Mandatory = $false, parametersetname = "Single")][Switch]$DomainData,
    [Parameter(Mandatory = $false, ParameterSetName = "Single")][Switch]$SharedDriveData,
    [Parameter(Mandatory = $false, ParameterSetName = "Single")][Switch]$OrgUnitData,
    [Parameter(Mandatory = $false, ParameterSetName = "All")][Switch]$All,
    [Parameter(Mandatory = $false)][Switch]$CreateOrUpdateSheet,
    [Parameter(Mandatory = $false)][String]$SheetId
)

function Get-Multivalues {
    param(
        $multivalues
    )

    $returnArray = @()
    foreach ($multivalue in $multivalues) {
        $m = @()
        foreach ($property in $multivalue.psobject.properties) {
            if ([String]::IsNullOrEmpty($property.value) -eq $false) {
                $m += ($property.name + "=" + $property.value)
            }
        }
        $returnArray += ($m -join ";")
    }
    return ($returnArray -join ",")
}

$exportFiles = @{
    orgUnits          = $ExportPath + "/orgUnits.csv"
    users             = $ExportPath + "/users.csv"
    userAliases       = $ExportPath + "/userAliases.csv"
    groups            = $ExportPath + "/groups.csv"
    groupMembers      = $ExportPath + "/groupMembers.csv"
    groupAliases      = $ExportPath + "/groupAliases.csv"
    groupSettings     = $ExportPath + "/groupSettings.csv"
    delegates         = $ExportPath + "/delegates.csv"
    driveUsage        = $ExportPath + "/driveUsage.csv"
    domains           = $ExportPath + "/domains.csv"
    domainAliases     = $ExportPath + "/domainAliases.csv"
    buildings         = $ExportPath + "/buildings.csv"
    resourceCalendars = $ExportPath + "/resourceCalendars.csv"
    features          = $ExportPath + "/features.csv"
    drives            = $ExportPath + "/drives.csv"
    gmailProfiles     = $ExportPath + "/gmailProfiles.csv"
}

function Get-UserData {
    List-GSMUsers -Fields "users(primaryEmail,name,gender,orgUnitPath,recoveryEmail,recoveryPhone,addresses),nextPageToken" | Foreach-Object {
        $user = $_.primaryEmail
        New-Object PSObject -Property ([Ordered]@{
            primaryEmail  = $user
            familyName    = $_.name.familyName
            givenName     = $_.name.givenName
            genderType    = $_.gender.type
            orgUnitPath   = $_.orgUnitPath
            recoveryEmail = $_.recoveryEmail
            recoveryPhone = $_.recoveryPhone
            addresses     = Get-Multivalues -multivalues $_.addresses
        }) | Export-Csv -Path $exportFiles.users -Delimiter ',' -NoClobber -Append -Force
        List-GSMDelegates -DwdSubject $user | Foreach-Object {
            New-Object PSObject -Property ([Ordered]@{
                primaryEmail       = $user
                delegateEmail      = $_.delegateEmail
                verificationStatus = $_.verificationStatus
            }) | Export-Csv -Path $exportFiles.delegates -Delimiter ',' -NoClobber -Append -Force
        }
        $gmailProfile = GetProfile-GSMGmailUsers -DwdSubject $user
            New-Object PSObject -Property ([Ordered]@{
                emailAddress  = $user
                messagesTotal = $gmailProfile.messagesTotal
                threadsTotal  = $gmailProfile.threadsTotal
                historyId     = $gmailProfile.historyId
            }) | Export-Csv -Path $exportFiles.gmailProfiles -Delimiter ',' -NoClobber -Append -Force
        $about = Get-GSMAbout -DwdSubject $user -Fields "storageQuota(usage,usageInDrive)"
        $fileCount = 0
        List-GSMFiles -DwdSubject $user -Fields "files(id),nextPageToken" -Corpora user -Spaces drive -Q ("'" + $user + "' in owners and trashed = false") | ForEach-Object {$fileCount++}
        New-Object PSObject -Property ([Ordered]@{
            userId               = $user
            'usageInDrive (GB)'  = [Math]::Round((($about.storageQuota).usageInDrive / 1GB), 2)
            files                = $fileCount
            'usageInOthers (GB)' = [Math]::Round(((($about.storageQuota).usage - ($about.storageQuota).usageInDrive) / 1GB), 2)
        }) | Export-Csv -Path $exportFiles.driveUsage -Delimiter ',' -NoClobber -Append -Force
    }
    List-GSMUserAliasesBatch -Path $exportFiles.users -Delimiter "," -UserKey 1 -SkipHeader | ForEach-Object {
        foreach ($userAlias in $_.aliases) {
            New-Object PSObject -Property ([Ordered]@{
                    primaryEmail = $userAlias.primaryEmail
                    alias        = $userAlias.alias
                }) | Export-Csv -Path $exportFiles.userAliases -Delimiter ',' -NoClobber -Append -Force
        }
    }
}

function Get-GroupData {
    List-GSMGroups -Fields "groups(email,name,description),nextPageToken" | ForEach-Object {
        New-Object PSObject -Property ([Ordered]@{
            email       = $_.email
            name        = $_.name
            description = $_.description
        }) | Export-Csv -Path $exportFiles.groups -Delimiter ',' -NoClobber -Append -Force
    }
    List-GSMMembersBatch -Path $exportFiles.groups -Delimiter "," -GroupKey 1 -SkipHeader | ForEach-Object {
        foreach ($member in $_.members) {
            New-Object PSObject -Property ([Ordered]@{
                    groupKey = $_.groupKey
                    email    = $member.email
                    role     = $member.role
                }) | Export-Csv -Path $exportFiles.groupMembers -Delimiter ',' -NoClobber -Append -Force
        }
    }
    List-GSMGroupAliasesBatch -Path $exportFiles.groups -GroupKey 1 -Delimiter "," -SkipHeader | ForEach-Object {
        foreach ($groupAlias in $_.aliases) {
            New-Object PSObject -Property ([Ordered]@{
                    groupKey = $_.groupKey
                    alias    = $groupAlias.alias
                }) | Export-Csv -Path $exportFiles.groupAliases -Delimiter ',' -NoClobber -Append -Force
        }
    }
    Get-GSMGroupSettingsBatch -Path $exportFiles.groups -GroupUniqueId 1 -Delimiter "," -SkipHeader -Fields_ALL "allowExternalMembers,allowWebPosting,archiveOnly,email,enableCollaborativeInbox,favoriteRepliesOnTop,includeCustomFooter,includeInGlobalAddressList,isArchived,membersCanPostAsTheGroup,messageModerationLevel,name,replyTo,sendMessageDenyNotification,spamModerationLevel,whoCanApproveMembers,whoCanAssistContent,whoCanBanUsers,whoCanContactOwner,whoCanDiscoverGroup,whoCanJoin,whoCanLeaveGroup,whoCanModerateContent,whoCanModerateMembers,whoCanPostMessage,whoCanViewGroup,whoCanViewMembership" | Foreach-Object {
        $_ | Export-Csv -Path $exportFiles.groupSettings -Delimiter ',' -NoClobber -Append -Force
    }
}

function Get-ResourceData {
    List-GSMBuildings -Fields "buildings(buildingId,buildingName,description,floorNames)" | Foreach-Object {
        New-Object PSObject -Property ([Ordered]@{
            buildingId   = $_.buildingId
            buildingName = $_.buildingName
            description  = $_.description
            floorNames   = $_.floorNames -join ","
        }) | Export-Csv -Path $exportFiles.buildings -Delimiter ',' -NoClobber -Append -Force
    }
    List-GSMCalendarResources -Fields "items(buildingId,capacity,floorName,generatedResourceName,resourceCategory,resourceEmail,resourceId,resourceName)" | Foreach-Object {
        $_ | Export-Csv -Path $exportFiles.resourceCalendars -Delimiter ',' -NoClobber -Append -Force
    }
    List-GSMFeatures -Fields "features(name)" | Foreach-Object {
        $_ | Export-Csv -Path $exportFiles.features -Delimiter ',' -NoClobber -Append -Force
    }
}

function Get-DomainData {
    List-GSMDomains -Fields "domains(domainName,verified,isPrimary)" | Foreach-Object {
        $_ | Export-Csv -Path $exportFiles.domains -Delimiter ',' -NoClobber -Append -Force
    }
    List-GSMDomainAliases -Fields "domainAliases(domainAliasName,parentDomainName,verified)" | Foreach-Object {
        $_ | Export-Csv -Path $exportFiles.domainAliases -Delimiter ',' -NoClobber -Append -Force
    }
}

function Get-SharedDriveData {
    $admin = (Get-GSMAbout -Fields "user(emailAddress)").user.emailAddress
    List-GSMDrives -UseDomainAdminAccess | Foreach-Object {
        $adminPermission = Create-GSMPermissions -EmailAddress $admin -UseDomainAdminAccess -Role reader -FileId $_.id -SendNotificationEmail:$false -Type user
        $driveSize = GetSize-GSMDrives -DriveId $_.id
        $null = Delete-GSMPermissions -PermissionId $adminPermission.id -FileId $_.id -UseDomainAdminAccess
        New-Object PSObject -Property ([Ordered]@{
                driveId     = $_.id
                driveName   = $_.name
                files       = $driveSize.files
                folders     = $driveSize.folders
                'size (GB)' = [Math]::Round($driveSize.size / 1GB, 2)
            }) | Export-Csv -Path $exportFiles.drives -Delimiter ',' -NoClobber -Append -Force
    }
}

function Get-OrgUnitData {
    List-GSMOrgUnits -Type all -Fields "organizationUnits(name,orgUnitPath,parentOrgUnitPath)" | Foreach-Object {
        $_ | Export-Csv -Path $exportFiles.orgUnits -Delimiter ',' -NoClobber -Append -Force
    }
}

function Export-Sheet {
    param (
        [Parameter(Mandatory = $false)][String]$SheetId
    )

    $sheets = @()
    foreach ($exportFile in $exportFiles.Keys) {
        if (Test-Path $exportFiles.$exportFile) {
            $sheets += "title=" + $exportFile + ";path=" + $exportFiles.$exportFile
        }
    }
    if ([String]::IsNullOrEmpty($SheetId)) {
        Create-GSMSpreadsheets -Title $Config -Fields "spreadsheetUrl,spreadsheetId" -CsvFileToUpload ($sheets -join ",")
    }
    else {
        $null = BatchUpdate-GSMSpreadsheets -SpreadsheetId $SheetId -Fields "spreadsheetId" -CsvFileToUpload ($sheets -join ",")
        Get-GSMSpreadsheets -SpreadsheetId $SheetId -Fields "spreadsheetUrl,spreadsheetId"
    }
}

Load-GSMConfigs -Name $Config

if ($UserData -or $All) {
    Get-UserData
}
if ($GroupData -or $All) {
    Get-GroupData
}
if ($ResourceData -or $All) {
    Get-ResourceData
}
if ($DomainData -or $All) {
    Get-DomainData
}
if ($SharedDriveData -or $All) {
    Get-SharedDriveData
}
if ($OrgUnitData -or $All) {
    Get-OrgUnitData
}
if ($CreateOrUpdateSheet) {
    Export-Sheet -SheetId $SheetId
}

Save the script as a .ps1 file and use it like this:

./Export-Stuff.ps1 -ExportPath ./exports -Config myConfig -UserData -GroupData

This will create CSV files for user data and group data in ./exports for the domain speficied in myConfig

./Export-Stuff.ps1 -ExportPath ./exports -Config myConfig -All -CreateOrUpdateSheet

This will create CSV files for all data in ./exports for the domain speficied in myConfig and create a Google Sheet file in the drive of the subject specified in myConfig.

SEE ALSO