PSWorkspaceOneAccess.psm1
<# .SYNOPSIS Opens a connection to Workspace ONE Access. .DESCRIPTION Generates an OAuth token using client credentials and retrieves the access token for Workspace ONE Access. .PARAMETER ClientId The client ID for the Workspace ONE Access API. .PARAMETER ClientSecret The client secret for the Workspace ONE Access API. .PARAMETER AccessURL The base URL for Workspace ONE Access. .EXAMPLE $token = Open-WS1AccessConnection -ClientId "myClientId" -ClientSecret "mySecret" -AccessURL "access.workspaceone.com" #> Function Open-WS1AccessConnection { param ( [string]$ClientId, [string]$ClientSecret, [string]$AccessURL ) $text = "${ClientId}:${ClientSecret}" $base64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($text)) $headers = @{ "Authorization" = "Basic $base64" "Content-Type" = "application/x-www-form-urlencoded" } try { $results = Invoke-WebRequest -Uri "https://${AccessURL}/SAAS/auth/oauthtoken?grant_type=client_credentials" -Method POST -Headers $headers -ErrorAction Stop return ($results.Content | ConvertFrom-Json).access_token } catch { Write-Error "Failed to retrieve access token for URL ${AccessURL} with client ${ClientId}: $($_.Exception.Message)" return $null } } <# .SYNOPSIS Retrieves the Workspace ONE Magic Token. .DESCRIPTION Requests a one-time login link (Magic Token) for a specific user within Workspace ONE. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .PARAMETER Domain The domain name of the user. .PARAMETER Username The username for which to retrieve the Magic Token. .EXAMPLE $link = Get-WS1MagicToken -AccessToken $token -AccessURL "access.workspaceone.com" -Domain "myDomain" -Username "john.doe" #> Function Get-WS1MagicToken { param ( [string]$AccessToken, [string]$AccessURL, [string]$Domain, [string]$Username ) $headers = @{ "Accept" = "application/vnd.vmware.horizon.manager.tokenauth.link.response+json" "Authorization" = "Bearer $AccessToken" "Content-Type" = "application/vnd.vmware.horizon.manager.tokenauth.generation.request+json" } $body = @{ domain = $Domain userName = $Username } | ConvertTo-Json try { $response = Invoke-RestMethod -Uri "https://${AccessURL}/SAAS/jersey/manager/api/token/auth/state" -Method POST -Headers $headers -Body $body -ErrorAction Stop return $response.loginLink } catch { Write-Error "Failed to get Magic Token for user ${Username} from ${AccessURL}: $($_.Exception.Message)" return $null } } <# .SYNOPSIS Resets a Workspace ONE Magic Token for a user. .DESCRIPTION Deletes the current Magic Token for a user and generates a new one. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .PARAMETER Domain The domain name of the user. .PARAMETER Username The username for whom to reset the Magic Token. .EXAMPLE $newLink = Reset-WS1MagicToken -AccessToken $token -AccessURL "access.workspaceone.com" -Domain "myDomain" -Username "john.doe" #> Function Reset-WS1MagicToken { [CmdletBinding(SupportsShouldProcess = $true)] param ( [string]$AccessToken, [string]$AccessURL, [string]$Domain, [string]$Username ) try { if ($PSCmdlet.ShouldProcess('Removing user')) { Remove-WS1MagicToken -AccessToken $AccessToken -AccessURL $AccessURL -Username $Username $loginLink = Get-WS1MagicToken -AccessToken $AccessToken -AccessURL $AccessURL -Domain $Domain -Username $Username return $loginLink } } catch { Write-Error "Failed to reset Magic Token for user ${Username} at ${AccessURL}: $($_.Exception.Message)" return $null } } <# .SYNOPSIS Removes a Workspace ONE Magic Token for a user. .DESCRIPTION Deletes the Magic Token associated with a specified user. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .PARAMETER Username The username whose Magic Token is to be removed. .EXAMPLE Remove-WS1MagicToken -AccessToken $token -AccessURL "access.workspaceone.com" -Username "john.doe" #> Function Remove-WS1MagicToken { [CmdletBinding(SupportsShouldProcess = $true)] param ( [string]$AccessToken, [string]$AccessURL, [string]$Username ) $headers = @{ "Accept" = "application/vnd.vmware.horizon.manager.tokenauth.link.response+json" "Authorization" = "Bearer $AccessToken" "Content-Type" = "application/vnd.vmware.horizon.manager.tokenauth.generation.request+json" } try { $user = Get-WS1UserByUsername -AccessToken $AccessToken -AccessURL $AccessURL -Username $Username if (-not $user) { throw "User ${Username} not found" } $userId = $user.id if ($PSCmdlet.ShouldProcess('Removing magic token')) { Invoke-RestMethod -Uri "https://${AccessURL}/SAAS/jersey/manager/api/token/auth/state/$userId" -Method DELETE -Headers $headers -ErrorAction Stop # return "Magic Token for ${Username} removed successfully." } } catch { Write-Error "Failed to remove Magic Token for user ${Username} at ${AccessURL}: $($_.Exception.Message)" # return $null } } <# .SYNOPSIS Adds a new user to Workspace ONE. .DESCRIPTION Creates a new user in Workspace ONE with specified details. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .PARAMETER Username The username for the new user. .PARAMETER GivenName The given name of the user. .PARAMETER FamilyName The family name of the user. .PARAMETER Phone The phone number of the user. .PARAMETER Email The email address of the user. .PARAMETER Organization The organization name for the user. .EXAMPLE Add-WS1User -AccessToken $token -AccessURL "access.workspaceone.com" -Username "new.user" -GivenName "New" -FamilyName "User" -Phone "1234567890" -Email "new.user@example.com" -Organization "Sales" #> Function Add-WS1User { [CmdletBinding(SupportsShouldProcess = $true)] param ( [string]$AccessToken, [string]$AccessURL, [string]$Username, [string]$GivenName, [string]$FamilyName, [string]$Phone, [string]$Email, [string]$Organization ) $headers = @{ "Authorization" = "Bearer $AccessToken" "Content-Type" = "application/json" } $body = @{ "schemas" = @( "urn:scim:schemas:extension:workspace:tenant:itq-consultancy-b-v-2714:1.0", "urn:scim:schemas:extension:workspace:mfa:1.0", "urn:scim:schemas:extension:workspace:1.0", "urn:scim:schemas:extension:enterprise:1.0", "urn:scim:schemas:core:1.0" ) "name" = @{ "givenName" = $GivenName "familyName" = $FamilyName } "userName" = $Username "emails" = @( @{ value = $Email } ) "phoneNumbers" = @( @{ value = $Phone } ) "urn:scim:schemas:extension:workspace:1.0" = @{ "domain" = "ssp" "userPrincipalName" = $Username } "urn:scim:schemas:extension:enterprise:1.0" = @{ "organization" = $Organization } "urn:scim:schemas:extension:workspace:tenant:itq-consultancy-b-v-2714:1.0" = @{ "telephoneNumber" = $Phone } } | ConvertTo-Json -Depth 5 try { if ($PSCmdlet.ShouldProcess('Adding user')) { $response = Invoke-RestMethod -Uri "https://${AccessURL}/SAAS/jersey/manager/api/scim/Users" -Method POST -Headers $headers -Body $body -ErrorAction Stop return $response } } catch { Write-Error "Failed to add user ${Username} to Workspace ONE at ${AccessURL}: $($_.Exception.Message)" return $null } } <# .SYNOPSIS Updates an existing user's information in Workspace ONE. .DESCRIPTION Modifies the details of a specified user in Workspace ONE, such as name, phone, and email. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .PARAMETER UserId The unique identifier of the user to be updated. .PARAMETER GivenName The updated given name of the user. .PARAMETER FamilyName The updated family name of the user. .PARAMETER Username The updated username of the user. .PARAMETER Phone The updated phone number of the user. .PARAMETER Email The updated email address of the user. .EXAMPLE Update-WS1User -AccessToken $token -AccessURL "access.workspaceone.com" -UserId "12345" -GivenName "Updated" -FamilyName "User" -Username "updated.user" -Phone "9876543210" -Email "updated.user@example.com" #> Function Update-WS1User { [CmdletBinding(SupportsShouldProcess = $true)] param ( [string]$AccessToken, [string]$AccessURL, [string]$UserId, [string]$GivenName, [string]$FamilyName, [string]$Username, [string]$Phone, [string]$Email ) $headers = @{ "Authorization" = "Bearer $AccessToken" "Content-Type" = "application/json" } $body = @{ "schemas" = @( "urn:scim:schemas:extension:workspace:tenant:itq-consultancy-b-v-2714:1.0", "urn:scim:schemas:extension:workspace:mfa:1.0", "urn:scim:schemas:extension:workspace:1.0", "urn:scim:schemas:extension:enterprise:1.0", "urn:scim:schemas:core:1.0" ) "name" = @{ "givenName" = $GivenName "familyName" = $FamilyName } "userName" = $Username "emails" = @( @{ value = $Email } ) "phoneNumbers" = @( @{ value = $Phone } ) "urn:scim:schemas:extension:workspace:tenant:itq-consultancy-b-v-2714:1.0" = @{ "telephoneNumber" = $Phone } } | ConvertTo-Json try { if ($PSCmdlet.ShouldProcess('Updating user')) { $response = Invoke-RestMethod -Uri "https://${AccessURL}/SAAS/jersey/manager/api/scim/Users/$UserId" -Method PATCH -Headers $headers -Body $body -ErrorAction Stop return $response } } catch { Write-Error "Failed to update user ${UserId} at ${AccessURL}: $($_.Exception.Message)" return $null } } <# .SYNOPSIS Removes a user from Workspace ONE. .DESCRIPTION Deletes a user account from Workspace ONE based on the specified user ID. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .PARAMETER UserId The unique identifier of the user to be removed. .EXAMPLE Remove-WS1User -AccessToken $token -AccessURL "access.workspaceone.com" -UserId "12345" #> Function Remove-WS1User { [CmdletBinding(SupportsShouldProcess = $true)] param ( [string]$AccessToken, [string]$AccessURL, [string]$UserId ) $headers = @{ "Authorization" = "Bearer $AccessToken" "Content-Type" = "application/json" } try { if ($PSCmdlet.ShouldProcess('Removing user')) { Invoke-RestMethod -Uri "https://${AccessURL}/SAAS/jersey/manager/api/scim/Users/$UserId" -Method DELETE -Headers $headers -ErrorAction Stop #return "User ${UserId} removed successfully." } } catch { Write-Error "Failed to remove user ${UserId} at ${AccessURL}: $($_.Exception.Message)" #return $null } } <# .SYNOPSIS Retrieves information for a specific Workspace ONE user. .DESCRIPTION Fetches details of a user based on their username in Workspace ONE. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .PARAMETER Username The username of the user to retrieve. .EXAMPLE $userInfo = Get-WS1UserByUsername -AccessToken $token -AccessURL "access.workspaceone.com" -Username "john.doe" #> Function Get-WS1UserByUsername { param ( [string]$AccessToken, [string]$AccessURL, [string]$Username ) $apiEndpoint = "/SAAS/jersey/manager/api/scim/Users" $username = $username.Replace("@", "%40") $filter = "?filter=userName%20eq%20%22$username%22&sortOrder=descending" $url = "https://$AccessURL$apiEndpoint$filter" $headers = @{ "Authorization" = "Bearer $AccessToken" "Content-Type" = "application/json" } try { $response = Invoke-RestMethod -Uri $url -Method GET -Headers $headers -ErrorAction Stop return $response.Resources | Select-Object -First 1 } catch { Write-Error "Failed to retrieve user ${Username} from ${AccessURL}: $($_.Exception.Message)" return $null } } <# .SYNOPSIS Retrieves a list of all users in Workspace ONE. .DESCRIPTION Fetches information about all users in the Workspace ONE environment. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .EXAMPLE $users = Get-WS1User -AccessToken $token -AccessURL "access.workspaceone.com" #> Function Get-WS1User { param ( [string]$AccessToken, [string]$AccessURL ) $headers = @{ "Authorization" = "Bearer $AccessToken" "Content-Type" = "application/json" } try { $response = Invoke-RestMethod -Uri "https://${AccessURL}/SAAS/jersey/manager/api/scim/Users?count=9999" -Method GET -Headers $headers -ErrorAction Stop return $response.Resources } catch { Write-Error "Failed to get users at ${AccessURL}: $($_.Exception.Message)" return $null } } <# .SYNOPSIS Retrieves a specific Workspace ONE directory configuration by Directory ID. .DESCRIPTION The `Get-WS1DirectoryById` function retrieves configuration details of a specific Workspace ONE directory using its Directory ID. It uses the Workspace ONE REST API for this operation. .PARAMETER AccessURL The base URL of the Workspace ONE Access tenant (e.g., mytenant.vmwareidentity.com). .PARAMETER AccessToken The OAuth2 token used to authenticate API requests. .PARAMETER DirectoryId The unique identifier of the Workspace ONE directory to retrieve. .EXAMPLE Get-WS1Directory -AccessURL "mytenant.vmwareidentity.com" -AccessToken "eyJhbGciOiJIUz..." -DirectoryId "12345" This example retrieves the directory configuration for the directory with ID `12345`. #> Function Get-WS1DirectoryById { param ( [string]$AccessURL, [string]$AccessToken, [string]$DirectoryId ) $headers = @{ "Authorization" = "Bearer $AccessToken" } try { $response = Invoke-WebRequest -Uri "https://$AccessURL/SAAS/jersey/manager/api/connectormanagement/directoryconfigs/" -Headers $headers -Method Get $directories = $response | ConvertFrom-Json | Select-Object -ExpandProperty items return $directories | Where-Object { $_.directoryId -eq $DirectoryId } } catch { Write-Error "Failed to retrieve the Workspace ONE directory: $_" return $null } } <# .SYNOPSIS Retrieves all Workspace ONE directory configurations. .DESCRIPTION The `Get-WS1Directory` function retrieves the configuration details of all Workspace ONE directories, regardless of type. It uses the Workspace ONE REST API for this operation. .PARAMETER AccessURL The base URL of the Workspace ONE Access tenant (e.g., mytenant.vmwareidentity.com). .PARAMETER accessToken The OAuth2 token used to authenticate API requests. .EXAMPLE Get-WS1Directory -AccessURL "mytenant.vmwareidentity.com" -accessToken "eyJhbGciOiJIUz..." This example retrieves all directory configurations in the Workspace ONE tenant. #> Function Get-WS1Directory { param ( [string]$AccessURL, [string]$accessToken ) $headers = @{ "Authorization" = "Bearer $accessToken" } try { $response = Invoke-WebRequest -Uri "https://$AccessURL/SAAS/jersey/manager/api/connectormanagement/directoryconfigs/" -Headers $headers -Method Get return ($response | ConvertFrom-Json | Select-Object -ExpandProperty items) } catch { Write-Error "Failed to retrieve Workspace ONE directories: $_" return $null } } <# .SYNOPSIS Triggers a synchronization for a specified Workspace ONE directory. .DESCRIPTION The `Sync-WS1Directory` function sends a request to sync a directory within Workspace ONE Access. It uses the Workspace ONE REST API and requires authentication through an access token. .PARAMETER DirectoryId The unique identifier of the Workspace ONE directory to be synchronized. .PARAMETER AccessURL The base URL of the Workspace ONE Access tenant (e.g., mytenant.vmwareidentity.com). .PARAMETER accessToken The OAuth2 token used to authenticate API requests. .EXAMPLE Sync-WS1Directory -DirectoryId "directory12345" -AccessURL "mytenant.vmwareidentity.com" -accessToken "eyJhbGciOiJIUz..." This example triggers a synchronization for the directory with the ID `directory12345`. #> Function Sync-WS1Directory { param ( [string]$DirectoryId, [string]$AccessURL, [string]$accessToken ) $baseUri = "https://$AccessURL" $apiEndpoint = "/SAAS/jersey/manager/api/connectormanagement/directoryconfigurations/$DirectoryId/sync/v2" $url = "$baseUri$apiEndpoint" $headers = @{ "Authorization" = "Bearer $accessToken" "Content-Type" = "application/vnd.vmware.horizon.manager.connector.management.directory.sync.trigger.v2+json" } $jsonBody = @{ "ignoreSafeguards" = $false } | ConvertTo-Json try { $response = Invoke-RestMethod -Method POST -Uri $url -Headers $headers -Body $jsonBody -ErrorAction Stop Write-Output "Directory $DirectoryId synced successfully." write-output $response } catch { Write-Error "Failed to sync directory: $_" } } <# .SYNOPSIS Retrieves login audit events for a specific user. .DESCRIPTION Fetches login audit logs for a specified user in Workspace ONE. .PARAMETER AccessToken The OAuth access token to authenticate API requests. .PARAMETER AccessURL The base URL for Workspace ONE Access. .PARAMETER Username The username for which to retrieve login audit logs. .PARAMETER StartDate The start date for the query range (optional, default is 30 days ago). .PARAMETER EndDate The end date for the query range (optional, default is the current date). .PARAMETER PageSize The number of records to retrieve per page (optional, default is 1000). .EXAMPLE $auditLogs = Get-WS1LoginAuditForUser -AccessToken $token -AccessURL "access.workspaceone.com" -Username "john.doe" This will retrieve login audit events for the user "john.doe" within the last 30 days. .EXAMPLE $auditLogs = Get-WS1LoginAuditForUser -AccessToken $token -AccessURL "access.workspaceone.com" -Username "john.doe" -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) This will retrieve login audit events for the user "john.doe" within the last 7 days. #> Function Get-WS1LoginAuditForUser { param ( [string]$AccessToken, [string]$AccessURL, [string]$Username, [datetime]$StartDate = (Get-Date).AddDays(-30), # Default to last 30 days [datetime]$EndDate = (Get-Date), [int]$PageSize = 1000 ) $apiEndpoint = "/analytics/reports/audit" $username = $Username.Replace("@", "%40") # Convert StartDate and EndDate to epoch milliseconds $fromMillis = [math]::Round((($StartDate - (Get-Date "1970-01-01"))).TotalMilliseconds) $toMillis = [math]::Round((($EndDate - (Get-Date "1970-01-01"))).TotalMilliseconds) # Construct the filter query string (no actorUserName filter for this test) $filter = "?fromMillis=$fromMillis&toMillis=$toMillis&objectType=LOGIN&pageSize=$PageSize" $url = "https://$AccessURL$apiEndpoint$filter" $headers = @{ "Authorization" = "Bearer $AccessToken" "Content-Type" = "application/json" } write-output "Requesting data from: $url" try { # Make the API request $response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get # Check if the data array is empty if ($response.data.Count -eq 0) { Write-Warning "No login events found for user $Username between $StartDate and $EndDate" } else { # Loop through and format the response for better clarity foreach ($event in $response.data) { $timestamp = [datetime]::FromFileTimeUtc($event[0]) # Convert from milliseconds to datetime $userDomain = $event[1] $eventType = $event[2] $details = $event[4] | ConvertFrom-Json # Convert the event details JSON into a PowerShell object write-output "Date and Time: $timestamp" write-output "User Domain: $userDomain" write-output "Event Type: $eventType" write-output "Details: $($details | ConvertTo-Json -Depth 3)" write-output "--------------------------------------------" } } return $response } catch { Write-Error "Failed to retrieve login audit logs: $($_.Exception.Message)" return $null } } <# .SYNOPSIS Retrieves login audit events or other object types for a specified date range. .DESCRIPTION This function retrieves audit events from the Workspace ONE Access API for a specified date range. It allows filtering by object type (default is LOGIN events) and can return data in pages with a specified page size. The function converts the provided date range into epoch milliseconds and constructs the appropriate API URL to fetch the audit data. .PARAMETER AccessURL The base URL for the Workspace ONE Access service. .PARAMETER AccessToken The OAuth access token used to authenticate the API requests. .PARAMETER StartDate The start date of the audit query range (required). This date is converted to epoch milliseconds for the API query. .PARAMETER EndDate The end date of the audit query range (required). This date is converted to epoch milliseconds for the API query. .PARAMETER ObjectType The type of object for the audit events (optional, default is "LOGIN"). Other object types may include "LAUNCH", "GROUP", etc. .PARAMETER PageSize The number of records to retrieve per page (optional, default is 5000). The API supports up to 5000 records per request. .EXAMPLE $auditLogs = Get-WS1LoginAuditForDateRange -AccessURL "access.workspaceone.com" -AccessToken $token -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) This will retrieve LOGIN audit events for the last 7 days. .EXAMPLE $auditLogs = Get-WS1LoginAuditForDateRange -AccessURL "access.workspaceone.com" -AccessToken $token -StartDate (Get-Date).AddMonths(-1) -EndDate (Get-Date) -ObjectType "LAUNCH" This will retrieve LAUNCH audit events for the last month. #> Function Get-WS1LoginAuditForDateRange { param ( [string]$AccessURL, [string]$AccessToken, [datetime]$StartDate, [datetime]$EndDate, [string]$ObjectType = "LOGIN", # Default to LOGIN events, modify as needed [int]$PageSize = 5000 # Default page size ) $headers = @{ "Authorization" = "Bearer $AccessToken" "Accept" = "application/json" # Adjusted for the new API response type } # Convert dates to epoch milliseconds (correct format) $fromMillis = [math]::Round((($StartDate - (Get-Date "1970-01-01"))).TotalMilliseconds) $toMillis = [math]::Round((($EndDate - (Get-Date "1970-01-01"))).TotalMilliseconds) # Ensure fromMillis and toMillis are valid (positive numbers) if ($fromMillis -lt 0 -or $toMillis -lt 0) { Write-Error "Invalid date conversion. Please check the StartDate and EndDate parameters." return } # Construct the URL with additional query parameters $url = "https://$AccessURL/analytics/reports/audit?fromMillis=$fromMillis&toMillis=$toMillis&objectType=$ObjectType&pageSize=$PageSize" try { # Invoke the API call $response = Invoke-RestMethod -Method GET -Uri $url -Headers $headers -ErrorAction Stop # Display the full response for debugging write-output "Audit report retrieved successfully." # Loop through the data and format it for better readability foreach ($event in $response.data) { $timestamp = [datetime]::FromFileTimeUtc($event[0]) # Convert timestamp from milliseconds $userDomain = $event[1] $eventType = $event[2] $details = $event[4] | ConvertFrom-Json # Convert the JSON string to an object write-output "Date and Time: $timestamp" write-output "User Domain: $userDomain" write-output "Event Type: $eventType" write-output "Details: $($details | ConvertTo-Json -Depth 3)" write-output "--------------------------------------------" } # Return the full response if you still want to use it further return $response } catch { Write-Error "Failed to retrieve audit report: $_" } } |