PSOkta.psm1
# Setup "module scope" variables, credit to Joel Bennett @jaykul and Mike Robbins @mikerobbins $Script:PSOktaApiDomain = '' $Script:PSOktaApiHeaders = '' $Script:PSOktaApiVersion = 'v1' $Script:PSOktaVerbose = $true $VerbosePreference = "Continue" function Connect-PSOkta () { $Domain = Read-Host -Prompt "Please provide your Okta Domain" $Script:PSOktaApiDomain = "https://{0}-admin.okta.com/api/{1}" -f $Domain, $PSOktaApiVersion if (Test-Path -Path ( -join ($HOME, '/.PSOktaToken'))) { $Token = Import-Clixml -Path ( -join ($HOME, '/.PSOktaToken')) | ConvertFrom-SecureString -AsPlainText } else { $Token = Read-Host -AsSecureString -Prompt "Please provide your Okta API Token" | ConvertFrom-SecureString -AsPlainText } $Script:PSOktaApiHeaders = @{ Authorization = "SSWS {0}" -f $Token Accept = "application/json" "Content-Type" = "application/json" } } function Get-Okta { <# .Synopsis Get User, Groups or Apps data from Okta. .Description This "Magic" Okta function, breaks the rules with style, by allowing you to get User, Groups and Apps data from Okta, in a single command. .Example # Get a single user and return the user profile. Get-Okta -Version "v1" -Endpoint Users -Q "username@hillsong.com" .Example # Get all users. Note: The -Version paramater defaults to "v1" and can be ommitted. Get-Okta -Endpoint Users .Example # Get Okta ACTIVE users. # Note: As long as you provide the Endpoint parameter values "Users, Groups or Apps" in parameter position 0, you can omit the "-Endpoint" paramter. Get-Okta Users -Active .Example # Get all users starting with "bob" and return some useful objects Get-Okta Users -Q 'bob' -Verbose | select id,status,@{n='name';e={$_.profile.login}},created,lastlogin | ft #> [CmdletBinding()] Param ( [Parameter()] [String]$Version = $PSOktaApiVersion, [Parameter(Mandatory = $true, Position = 0)] [ValidateSet("Users", "Groups", "Apps")] [String]$Endpoint ) DynamicParam { $ParamOptions = @{ Users = @( @{ ParamName = "Q" ParamType = [String] ParamHelpMessage = "Enter an email address, first or last name to search for." ParamSet = "Q" }, @{ ParamName = "Simple" ParamType = [Switch] ParamHelpMessage = "Returns a simple subset of results" ParamSet = "Q" }, @{ ParamName = "All" ParamType = [Switch] ParamHelpMessage = "Will return all users." ParamSet = "All" }, @{ ParamName = "Active" ParamType = [Switch] ParamHelpMessage = "Will return active users." ParamSet = "Active" }, @{ ParamName = "Locked" ParamType = [Switch] ParamHelpMessage = "Will return locked users." ParamSet = "Locked" }, @{ ParamName = "PasswordExpired" ParamType = [Switch] ParamHelpMessage = "Will return password expired users" ParamSet = "PasswordExpired" }, @{ ParamName = "LastUpdated" ParamType = [Int] ParamValidateRange = "1", "90" ParamHelpMessage = "Will search for users last updated {n} days ago" ParamSet = "LastUpdated" }, @{ ParamName = "Department" ParamType = [String] ParamHelpMessage = "Enter the beginning characters or department name to search for." ParamSet = "Department" } ) Groups = @( @{ ParamName = "LastMembershipUpdated" ParamType = [Int] ParamValidateRange = "1", "90" ParamHelpMessage = "Will search for users last updated {n}d days ago" }, @{ ParamName = "Type" ParamType = [String] ParamValidateSet = "APP_GROUP", "BUILT_IN", "OKTA_GROUP" ParamHelpMessage = "Enter a group type to search for." } ) Apps = @( @{ ParamName = "Active" ParamType = [Switch] ParamHelpMessage = "Will return active users." }, @{ ParamName = "InActive" ParamType = [Switch] ParamHelpMessage = "Will return inactive users." } ) } $RuntimeDefinedParameterDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary function AddDynamicParams ($ParamName, $ParamType, $ParamValidateSet, $ParamHelpMessage, $ParamValidateRange, $ParamSet) { $Collection = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute] $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute $ParameterAttribute.Mandatory = $false $ParameterAttribute.HelpMessage = $ParamHelpMessage if ($ParamSet) { $ParameterAttribute.ParameterSetName = $ParamSet } $Collection.Add($ParameterAttribute) if ($ParamValidateRange) { $ValidateRangeAttribute = New-Object System.Management.Automation.ValidateRangeAttribute($ParamValidateRange) $Collection.Add($ValidateRangeAttribute) } if ($ParamValidateSet) { $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($ParamValidateSet) $Collection.Add($ValidateSetAttribute) } $RuntimeDefinedParameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParamName, $ParamType, $Collection) $RuntimeDefinedParameterDictionary.Add($ParamName, $RuntimeDefinedParameter) } switch ($Endpoint) { 'Users' { $ParamOptions.Users.foreach{ AddDynamicParams -ParamName $_.ParamName -ParamType $_.ParamType -ParamValidateSet $_.ParamValidateSet -ParamHelpMessage $_.ParamHelpMessage -ParamValidateRange $_.ParamValidateRange -ParamSet $_.ParamSet } Break } 'Groups' { $ParamOptions.Groups.foreach{ AddDynamicParams -ParamName $_.ParamName -ParamType $_.ParamType -ParamValidateSet $_.ParamValidateSet -ParamHelpMessage $_.ParamHelpMessage -ParamValidateRange $_.ParamValidateRange } Break } 'Apps' { $ParamOptions.Apps.foreach{ AddDynamicParams -ParamName $_.ParamName -ParamType $_.ParamType -ParamHelpMessage $_.ParamHelpMessage } Break } Default {} } return $RuntimeDefinedParameterDictionary } begin { # Handle the parameters switch ($PSBoundParameters.Endpoint) { 'Users' { if ($PSBoundParameters.Q) { $QueryString = -join ("?q=", $PSBoundParameters.Q) } if ($PSBoundParameters.All) { $null = $QueryString } if ($PSBoundParameters.Active) { $QueryString = '?filter=status eq "ACTIVE"' } if ($PSBoundParameters.Locked) { $QueryString = '?filter=status eq "LOCKED_OUT"' } if ($PSBoundParameters.PasswordExpired) { $QueryString = '?filter=status eq "PASSWORD_EXPIRED"' } if ($PSBoundParameters.Department) { $QueryString = '?search=profile.department sw "{0}"' -f $PSBoundParameters.Department } if ($PSBoundParameters.LastUpdated) { $Days = $PSBoundParameters.LastUpdated $QueryString = '?filter=lastUpdated gt "{0}"' -f (Get-Date).AddDays(-$Days).ToString('yyyy-MM-ddT00:00:00.00Z') } } 'Groups' { if ($PSBoundParameters.Type) { $QueryString = -join ('?filter=type eq "{0}"', $PSBoundParameters.Type) } if ($PSBoundParameters.LastMembershipUpdated) { $Days = $PSBoundParameters.LastMembershipUpdated $QueryString = '?filter=lastUpdated gt "{0}"' -f (Get-Date).AddDays(-$Days).ToString('yyyy-MM-ddT00:00:00.00Z') } } 'Apps' { if ($PSBoundParameters.Active) { $QueryString = '?filter=status eq "ACTIVE"' } if ($PSBoundParameters.InActive) { $QueryString = '?filter=status eq "INACTIVE"' } } } $ApiParams = @{ Uri = -join (($PSOktaApiDomain), ("/{0}{1}" -f $Endpoint.ToLower(), $QueryString)) Method = "Get" FollowReLink = $true } } process { try { $r = Invoke-OktaApi @ApiParams } catch [Microsoft.PowerShell.Commands.HttpResponseException] { Write-Error "HttpResponseException" } catch { Write-Error $_.ErrorDetails.Message | ConvertFrom-Json | Out-String } if ($PSBoundParameters.Simple) { $r.foreach{ [pscustomobject]@{ Id = $_.id Status = $_.status Created = $_.created Lastlogin = $_.lastLogin DisplayName = $_.profile.displayName Email = $_.profile.login Title = $_.profile.title Department = $_.profile.department } } } else { # Unroll the pages $r.foreach{ $_ } } } } function Invoke-OktaApi { [CmdletBinding()] param ( # Uri [Parameter()] [String]$Uri, # Method [Parameter()] [string]$Method, # FollowReLink [Parameter()] [Switch]$FollowReLink ) begin { $ApiParams = @{ Uri = $Uri Method = $Method Headers = $PSOktaApiHeaders FollowRelLink = if ($PSBoundParameters.FollowReLink) { $true } else { $false } Verbose = $true } } process { try { $r = Invoke-RestMethod @ApiParams return $r } catch { Write-Error $_.ErrorDetails.Message | ConvertFrom-Json | Out-String } } end { } } function Set-Okta { [CmdletBinding()] param ( # Parameter help description [Parameter(ValueFromPipelineByPropertyName = $true, Mandatory = $true)] [String]$Id, [Parameter()] [Switch]$Activate, [Parameter()] [Switch]$Reactivate, [Parameter()] [Switch]$Deactivate, [Parameter()] [Switch]$Suspend, [Parameter()] [Switch]$Unsuspend ) process { Switch ($PSBoundParameters.Keys) { { "Activate", "Reactivate", "Deactivate", "Suspend", "Unsuspend" -contains $_ } { $ParamBuilder = @{ Uri = -join (($PSOktaApiDomain), ("/users/{0}/lifecycle/{1}" -f $PSBoundParameters.Id, $_.toLower())) Method = 'Post' } Break; } } $ApiParams = @{ Uri = $ParamBuilder.Uri Method = $ParamBuilder.Method } Invoke-OktaApi @ApiParams } } |