Created
April 3, 2018 15:16
-
-
Save dindoliboon/6047c842810226a2c8b4ff24c18d91af to your computer and use it in GitHub Desktop.
Windows PowerShell library for performing basic requests on Google Apps User resources.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
Windows PowerShell library for performing basic requests on Google Apps User resources. | |
These are general steps and may not follow the Google Dashboard step-by-step. | |
Requirements: | |
- .NET Framework 4.5 | |
https://www.microsoft.com/net/download/dotnet-framework-runtime | |
- .NET Core SDK 2.1.101 | |
https://www.microsoft.com/net/download/windows | |
- Windows PowerShell 5.1.16299.98 | |
$PSVersionTable.PSVersion | |
- nuget packages for Google.Apis.Admin.Directory.directory_v1 1.32.2.1170 | |
dotnet new throwaway-app --target-framework-override net471 | |
dotnet add package Newtonsoft.Json --version 10.0.2 | |
dotnet add package System.Net.Http --version 4.3.3 | |
dotnet add package Google.Apis.Auth --version 1.32.2 | |
dotnet add package Google.Apis --version 1.32.2 | |
dotnet add package Google.Apis.Core --version 1.32.2 | |
dotnet add package Google.Apis.Admin.Directory.directory_v1 --version 1.32.2.1170 | |
- Google Admin SDK Directory API access | |
Create custom administrator roles | |
https://support.google.com/a/answer/2406043?hl=en | |
1. Go to Admin roles. | |
https://admin.google.com/AdminHome#DomainSettings/notab=1&subtab=roles | |
2. Click CREATE A NEW ROLE. | |
3 Enter a Name and Description. | |
4. Under Admin API Privileges, assign Create, Read, and Update for Users. | |
5. Click Save. | |
6. Click on Admins tab, click on ASSIGN ADMINS. | |
7. Enter a user to assign access to, then click CONFIRM ASSIGNMENT. | |
- Google managed service account with a P12 certificate. | |
Using OAuth 2.0 for Server to Server Applications | |
https://developers.google.com/identity/protocols/OAuth2ServiceAccount | |
1. Go to Service Accounts. | |
https://console.developers.google.com/permissions/serviceaccounts | |
2. Either select an existing project or create a new project. | |
If you are creating a new project, enable Admin SDK API. | |
3. Click on CREATE SERVICE ACCOUNT. | |
4. Enter a service account name, check Furnish a new private key, select P12 | |
for key type, and check Enable G Suite Domain-wide Delegation. Remember the | |
service account ID. Click CREATE. | |
5. Go to https://admin.google.com, click Security. | |
Click on Advance settings, Manage API client access. | |
https://admin.google.com/AdminHome?chromeless=1#OGX:ManageOauthClients | |
6. For Client Name, enter the service account ID (from step 4). | |
For One or More API Scopes, enter https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.user.readonly | |
Click Authorize. | |
#> | |
New-Module -Name libGoogleAdminDirectoryV1 -ScriptBlock { | |
<# | |
.Synopsis | |
Authenticates PowerShell with Google Apps. | |
.PARAMETER P12CertificatePath | |
Complete path to your P12 certificate. | |
.PARAMETER P12CertificatePassword | |
P12 certificate password. | |
.PARAMETER ServiceAccount | |
Service Account or Client ID. | |
.PARAMETER ApplicationName | |
Name of your application. | |
.PARAMETER AdminUser | |
Admin with Google Admin SDK Directory API access. | |
.EXAMPLE | |
$params = @{ | |
P12CertificatePath = 'C:\myproject-ffffffffffff.p12' | |
P12CertificatePassword = 'notasecret' | |
ServiceAccount = '000000000000000000000' | |
ApplicationName = 'libGoogleAdminDirectoryV1.psm1' | |
AdminUser = 'myadmin@contoso.com' | |
} | |
New-Connection @params | |
.OUTPUTS | |
Exceptions are returned to the calling application. | |
#> | |
function New-Connection | |
{ | |
[CmdletBinding()] | |
Param | |
( | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$P12CertificatePath, | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$P12CertificatePassword = 'notasecret', | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$ServiceAccount, | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$ApplicationName, | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$AdminUser | |
) | |
# If any packages fail to load, check dependencies with $Error[0].Exception.LoaderExceptions | |
Add-Type -Path "$ENV:USERPROFILE\.nuget\packages\newtonsoft.json\10.0.2\lib\net45\Newtonsoft.Json.dll" | |
Add-Type -Path "$ENV:USERPROFILE\.nuget\packages\google.apis.core\1.32.2\lib\net45\Google.Apis.Core.dll" | |
Add-Type -Path "$ENV:USERPROFILE\.nuget\packages\google.apis.auth\1.32.2\lib\net45\Google.Apis.Auth.dll" | |
Add-Type -Path "$ENV:USERPROFILE\.nuget\packages\google.apis.auth\1.32.2\lib\net45\Google.Apis.Auth.PlatformServices.dll" | |
Add-Type -Path "$ENV:USERPROFILE\.nuget\packages\google.apis\1.32.2\lib\net45\Google.Apis.dll" | |
Add-Type -Path "$ENV:USERPROFILE\.nuget\packages\google.apis\1.32.2\lib\net45\Google.Apis.PlatformServices.dll" | |
Add-Type -Path "$ENV:USERPROFILE\.nuget\packages\google.apis.admin.directory.directory_v1\1.32.2.1170\lib\net45\Google.Apis.Admin.Directory.directory_v1.dll" | |
# Initializes a new instance of the X509Certificate2 class using a certificate file name, a password used to access the certificate, and a key storage flag. | |
$keyStorageFlags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable | |
$certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $P12CertificatePath, $P12CertificatePassword, $keyStorageFlags | |
# Add the minimum scope access to get user information. | |
# Reference: https://developers.google.com/admin-sdk/directory/v1/reference/users/get#auth | |
$scopes = New-Object -TypeName System.Collections.Generic.List[string] | |
$scopes.Add([Google.Apis.Admin.Directory.directory_v1.DirectoryService+Scope]::AdminDirectoryUser) | |
$scopes.Add([Google.Apis.Admin.Directory.directory_v1.DirectoryService+Scope]::AdminDirectoryUserReadonly) | |
# Constructs a new service account credential using the given service account id. | |
# Impersonate an user with Admin SDK Directory API access specified in AdminUser. | |
# https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#service-account | |
$credentialInitializer = New-Object -TypeName Google.Apis.Auth.OAuth2.ServiceAccountCredential+Initializer($ServiceAccount) | |
$credentialInitializer.Scopes = $scopes | |
$credentialInitializer.User = $AdminUser | |
$credential = New-Object -TypeName Google.Apis.Auth.OAuth2.ServiceAccountCredential($credentialInitializer).FromCertificate($certificate) | |
# Create client service object. | |
$userServiceInitializer = New-Object -TypeName Google.Apis.Services.BaseClientService+Initializer | |
$userServiceInitializer.HttpClientInitializer = $credential | |
$userServiceInitializer.ApplicationName = $ApplicationName | |
$Script:UserService = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.DirectoryService -ArgumentList $userServiceInitializer | |
} | |
<# | |
.Synopsis | |
Checks if a user exists in Google Apps. | |
.PARAMETER UserId | |
The user's primary email address to look for. | |
.EXAMPLE | |
Get-UserExists -UserId 'myuser@contoso.com' | |
.OUTPUTS | |
Returns $true if the user exists, otherwise $false. | |
Exceptions besides user not found are returned to the calling application. | |
#> | |
function Get-UserExists | |
{ | |
[CmdletBinding()] | |
[OutputType([Boolean])] | |
Param | |
( | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$UserId | |
) | |
$ret = $false | |
if ($null -ne $Script:UserService) | |
{ | |
# Request only the primaryEmail attribute. | |
$user = $null | |
$request = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.UsersResource+GetRequest -ArgumentList $Script:UserService, $UserId | |
$request.Fields = 'primaryEmail' | |
try | |
{ | |
$user = $request.Execute() | |
} | |
catch [Google.GoogleApiException] | |
{ | |
# Hide exceptions for user not found. | |
if ($_ -notlike '*Resource Not Found: userKey*') | |
{ | |
throw | |
} | |
} | |
if ($null -ne $user -and $user.PrimaryEmail.Length) | |
{ | |
# We have a valid user. | |
$ret = $true | |
} | |
} | |
else | |
{ | |
Write-Error -Message 'New-Connection() must be called first. See Get-Help -Name New-Connection -Full' | |
} | |
return $ret | |
} | |
<# | |
.Synopsis | |
Updates name or password for the user. | |
.PARAMETER UserId | |
The user's primary email address of the user to update. | |
.PARAMETER FirstName | |
Given name of the user. | |
.PARAMETER LastName | |
Surname of the user. | |
.PARAMETER Password | |
Password of the user. | |
.EXAMPLE | |
# Update the name of the user. | |
Set-User -UserId 'myuser@contoso.com' -FirstName 'John' -LastName 'Doe' | |
.EXAMPLE | |
# Update the password of the user. | |
Set-User -UserId 'myuser@contoso.com' -Password 'SuperSecur3!' | |
.OUTPUTS | |
Returns User Resource JSON string if successful. | |
https://developers.google.com/admin-sdk/directory/v1/reference/users | |
Exceptions are returned to the calling application. | |
#> | |
function Set-User | |
{ | |
[CmdletBinding()] | |
[OutputType([String])] | |
Param | |
( | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$UserId, | |
[String] | |
$FirstName, | |
[String] | |
$LastName, | |
[String] | |
$Password | |
) | |
$ret = '' | |
if ($null -ne $Script:UserService) | |
{ | |
# Create user template. | |
$gUser = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.Data.User | |
# Update specific properties if provided. | |
if ($FirstName.Length -gt 0 -or $FirstName.Length -gt 0) | |
{ | |
$gUser.Name = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.Data.UserName | |
$gUser.Name.GivenName = $FirstName | |
$gUser.Name.FamilyName = $LastName | |
} | |
if ($Password.Length -gt 0) | |
{ | |
# Get the MD5 hash value of the user password. | |
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider | |
$hash = [System.BitConverter]::ToString($md5.ComputeHash([Text.Encoding]::UTF8.GetBytes($Password))) -replace '-', '' | |
$gUser.Password = $hash | |
$gUser.HashFunction = 'MD5' | |
} | |
# Perform update, requesting primaryEmail and the name. | |
$request = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.UsersResource+PatchRequest -ArgumentList $Script:UserService, $gUser, $UserId | |
$request.Fields = 'primaryEmail,name/givenName,name/familyName' | |
$user = $request.Execute() | |
$ret = ConvertTo-Json -InputObject $user -Compress | |
} | |
else | |
{ | |
Write-Error -Message 'New-Connection() must be called first. See Get-Help -Name New-Connection -Full' | |
} | |
return $ret | |
} | |
<# | |
.Synopsis | |
Get selected fields of a user. | |
.PARAMETER UserId | |
The user's primary email address of the user to look for. | |
.PARAMETER Field | |
Comma-separated list of attributes to return. | |
See Users resource for available attributes. | |
https://developers.google.com/admin-sdk/directory/v1/reference/users | |
.EXAMPLE | |
Get-User -UserId 'myuser@contoso.com' -Field 'organizations,posixAccounts/username,primaryEmail' | |
.OUTPUTS | |
Returns User Resource JSON string if successful. | |
https://developers.google.com/admin-sdk/directory/v1/reference/users | |
Exceptions are returned to the calling application. | |
#> | |
function Get-User | |
{ | |
[CmdletBinding()] | |
[OutputType([String])] | |
Param | |
( | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$UserId, | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$Field | |
) | |
$ret = '' | |
if ($null -ne $Script:UserService) | |
{ | |
# Get requested fields. | |
$request = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.UsersResource+GetRequest -ArgumentList $Script:UserService, $UserId | |
$request.Fields = $Field | |
$user = $request.Execute() | |
$ret = ConvertTo-Json -InputObject $user -Compress | |
} | |
else | |
{ | |
Write-Error -Message 'New-Connection() must be called first. See Get-Help -Name New-Connection -Full' | |
} | |
return $ret | |
} | |
<# | |
.Synopsis | |
Create a new user. | |
.PARAMETER UserId | |
The user's primary email address. The primaryEmail must be unique and cannot be an alias of another user. | |
.PARAMETER Password | |
Password of the user. | |
.PARAMETER FirstName | |
Given name of the user. | |
.PARAMETER LastName | |
Surname of the user. | |
.PARAMETER OrgUnitPath | |
The full path of the parent organization associated with the user. If the parent organization is the top-level, it is represented as a forward slash (/). | |
.EXAMPLE | |
New-User -UserId 'myuser@contoso.com' -Password 'SuperSecur3!' -FirstName 'John' -LastName 'Doe' -OrgUnitPath '/' | |
.OUTPUTS | |
Returns User Resource JSON string if successful. | |
https://developers.google.com/admin-sdk/directory/v1/reference/users | |
Exceptions are returned to the calling application. | |
#> | |
function New-User | |
{ | |
[CmdletBinding()] | |
[OutputType([String])] | |
Param | |
( | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$UserId, | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$Password, | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$FirstName, | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$LastName, | |
[ValidateNotNullOrEmpty()] | |
[String] | |
$OrgUnitPath | |
) | |
$ret = '' | |
if ($null -ne $Script:UserService) | |
{ | |
# Get the MD5 hash value of the user password. | |
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider | |
$hash = [System.BitConverter]::ToString($md5.ComputeHash([Text.Encoding]::UTF8.GetBytes($Password))) -replace '-', '' | |
# Create user template. | |
$gUser = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.Data.User | |
$gUser.PrimaryEmail = $UserId | |
$gUser.Name = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.Data.UserName | |
$gUser.Name.GivenName = $FirstName | |
$gUser.Name.FamilyName = $LastName | |
$gUser.Password = $hash | |
$gUser.HashFunction = 'MD5' | |
$gUser.OrgUnitPath = $OrgUnitPath | |
# Perform update, requesting primaryEmail. | |
$request = New-Object -TypeName Google.Apis.Admin.Directory.directory_v1.UsersResource+InsertRequest -ArgumentList $Script:UserService, $gUser | |
$request.Fields = 'primaryEmail' | |
$user = $request.Execute() | |
$ret = ConvertTo-Json -InputObject $user -Compress | |
} | |
else | |
{ | |
Write-Error -Message 'New-Connection() must be called first. See Get-Help -Name New-Connection -Full' | |
} | |
return $ret | |
} | |
Export-ModuleMember -Function 'New-Connection', 'Get-UserExists', 'Set-User', 'Get-User', 'New-User' | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment