├── okta.json ├── .gitignore ├── Okta.psd1 ├── README.md ├── LICENSE └── Okta.psm1 /okta.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Powershell module for Okta managment APIs", 3 | "description": "A Powershell module that provides native Powershell capabilities on top of Okta's REST APIs", 4 | "categories": ["user management", "authentication", "authorization", "mfa", "sso", "apiAuthentication"] 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store 32 | .DS_Store? 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | ehthumbs.db 37 | Thumbs.db 38 | *~ 39 | .vscode 40 | 41 | # Sensitive personalized files # 42 | ################################ 43 | Okta_org.ps1 44 | .Okta_org.ps1.swp 45 | -------------------------------------------------------------------------------- /Okta.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | # Script module or binary module file associated with this manifest 3 | ModuleToProcess = 'Okta.psm1' 4 | 5 | # Version number of this module. 6 | ModuleVersion = '2.4' 7 | 8 | # ID used to uniquely identify this module 9 | GUID = 'c43305bd-6cdf-4a38-9b15-79ada42d9b9e' 10 | 11 | # Author of this module 12 | Author = 'Matt Egan' 13 | 14 | HelpInfoUri = 'https://github.com/mbegan/Okta-PSModule' 15 | 16 | # Company or vendor of this module 17 | CompanyName = '' 18 | 19 | # Copyright statement for this module 20 | Copyright = 'Use as you see fit, credit is always nice' 21 | 22 | # Description of the functionality provided by this module 23 | Description = 'This module contains powershell wrappers to leverage the Okta API functions described here http://developer.okta.com/docs/getting_started/design_principles.html' 24 | 25 | # Minimum version of the Windows PowerShell engine required by this module 26 | PowerShellVersion = '1.0' 27 | 28 | # Name of the Windows PowerShell host required by this module 29 | PowerShellHostName = '' 30 | 31 | # Minimum version of the Windows PowerShell host required by this module 32 | PowerShellHostVersion = '1.0' 33 | 34 | # Minimum version of the .NET Framework required by this module 35 | DotNetFrameworkVersion = '' 36 | 37 | # Minimum version of the common language runtime (CLR) required by this module 38 | CLRVersion = '' 39 | 40 | # Processor architecture (None, X86, Amd64, IA64) required by this module 41 | ProcessorArchitecture = '' 42 | 43 | # Modules that must be imported into the global environment prior to importing this module 44 | RequiredModules = @() 45 | 46 | # Assemblies that must be loaded prior to importing this module 47 | #RequiredAssemblies = @('') 48 | 49 | # Script files (.ps1) that are run in the caller's environment prior to importing this module 50 | ScriptsToProcess = @('Okta_org.ps1') 51 | 52 | # Type files (.ps1xml) to be loaded when importing this module 53 | #TypesToProcess = @('') 54 | 55 | # Format files (.ps1xml) to be loaded when importing this module 56 | #FormatsToProcess = @('') 57 | 58 | # Modules to import as nested modules of the module specified in ModuleToProcess 59 | NestedModules = @() 60 | 61 | # Functions to export from this module 62 | FunctionsToExport = 'okta*' 63 | 64 | # Cmdlets to export from this module 65 | CmdletsToExport = '' 66 | 67 | # Variables to export from this module 68 | VariablesToExport = '' 69 | 70 | # Aliases to export from this module 71 | AliasesToExport = '' 72 | 73 | # List of all modules packaged with this module 74 | ModuleList = @() 75 | 76 | # List of all files packaged with this module 77 | FileList = @('Okta.psm1','Okta.psd1','Okta_org.ps1') 78 | 79 | # Private data to pass to the module specified in ModuleToProcess 80 | PrivateData = '' 81 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Okta-PSModule Documentation 2 | 3 | This is not to be confused with or in competition with the official Okta [Powershell/CSharp module](https://github.com/okta/oktasdk-csharp/tree/master/Okta.Core.Automation). 4 | This is something I have been building and adding to for a few years. I still need the functionality it provides on a near daily basis so I figured it was time to share. 5 | 6 | -------- 7 | 8 | :information_source: **Disclaimer:** This tool is not an official Okta product and does not qualify for any Okta support. 9 | 10 | -------- 11 | 12 | ## Getting Started 13 | 14 | ### PreReq 15 | 16 | 1. This Module requires Powershell version 4 or greater (see output from `$PSVersionTable`) 17 | 18 | ```powershell 19 | PS > $PSVersionTable 20 | 21 | Name Value 22 | ---- ----- 23 | PSVersion 6.0.0-rc 24 | PSEdition Core 25 | GitCommitId v6.0.0-rc 26 | OS Darwin 17.4.0 Darwin Kernel Version 17.4.0: Sun Dec 17 09:19:54 PST 2017; root:xnu-4570.41.2~1/RELEASE_X86_64 27 | Platform Unix 28 | PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} 29 | PSRemotingProtocolVersion 2.3 30 | SerializationVersion 1.1.0.1 31 | WSManStackVersion 3.0 32 | ``` 33 | 34 | 2. This Module will run on both Windows and Mac/*nix version of powershell 35 | 36 | ### Installation 37 | 38 | 1. Download the module (git clone or download the zip) 39 | 2. Place the module in your PSModulePath hint [Read more about PSModulePath Here](https://msdn.microsoft.com/en-us/library/dd878324%28v=vs.85%29.aspx) 40 | 41 | ```powershell 42 | Write-Host $env:PSModulePath 43 | ``` 44 | 45 | 3. Get an API Token for your Okta Org [Getting an API Token](http://developer.okta.com/docs/getting_started/getting_a_token.html) 46 | 4. Create a file called Okta_org.ps1 (example content below) and save it in the directory with the Okta.psd1 and Okta.psm1 files. 47 | 48 | ```powershell 49 | <# Okta_org.ps1 #> 50 | # Verbose will print various informative messages 51 | [Boolean]$oktaVerbose = $true 52 | # define the default Okta Org you want to use, useful if you have more than one. 53 | [String]$oktaDefOrg = "prod" 54 | 55 | [Hashtable]$oktaOrgs = @{ 56 | prod1 = [Hashtable]@{ 57 | baseUrl = [String]"https://yourdomain.okta.com" 58 | secToken = [String]"yourApiToken" 59 | enablePagination = [boolean]$true 60 | pageSize = [int]500 61 | } 62 | prod2 = [Hashtable]@{ 63 | baseUrl = [String]"https://yourOtherdomain.okta.com" 64 | secToken = [String]"yourOtherApiToken" 65 | enablePagination = [boolean]$true 66 | pageSize = [int]500 67 | } 68 | prev = [HashTable]@{ 69 | baseUrl = [String]"https://yourDomain.oktapreview.com" 70 | secToken = [String]"yourPreviewApiToken" 71 | enablePagination = [boolean]$true 72 | pageSize = [int]500 73 | } 74 | } 75 | ``` 76 | 77 | ### Example Installation: 78 | 79 | 1. Open a command prompt 80 | 81 | ``` 82 | cd %userprofile%\Documents\WindowsPowerShell\Modules 83 | git clone https://github.com/mbegan/Okta-PSModule.git Okta 84 | cd Okta 85 | notepad Okta_org.ps1 86 | ``` 87 | 88 | 2. Paste the basic format for the Okta_org.ps1 file listed Above. 89 | 3. Modify file as required \(Update yourdomain, API Token you generated for that org etc\) 90 | 4. Save the file 91 | 92 | ### Basic Usage: 93 | 94 | 1. Launch powershell \(or even better, the powershell ise\) 95 | 2. Import the Okta Module 96 | 3. Use 97 | ```powershell 98 | PS C:\> Import-Module Okta 99 | 100 | PS C:\> oktaGetUserbyID -oOrg prod -uid mbegan@gmail.com 101 | [ GET https://varian.okta.com/api/v1/users/mbegan@gmail.com ] 102 | 103 | 104 | id : 00u103j904jPJACDTXXV 105 | status : ACTIVE 106 | created : 2014-12-23T22:50:41.000Z 107 | activated : 2014-12-23T22:50:41.000Z 108 | statusChanged : 2014-12-23T22:50:41.000Z 109 | lastLogin : 2015-01-30T23:48:05.000Z 110 | lastUpdated : 2015-01-30T23:41:41.000Z 111 | passwordChanged : 2015-01-30T23:41:41.000Z 112 | profile : @{email=mbegan@gmail.com; firstName=Matt; lastName=Egan; login=mbegan@gmail.com; mobilePhone=; secondEmail=} 113 | credentials : @{password=; recovery_question=; provider=} 114 | _links : @{resetPassword=; resetFactors=; expirePassword=; forgotPassword=; changeRecoveryQuestion=; deactivate=; changePassword=} 115 | ``` 116 | When elements are returned in the API they are powershell objects, you can treat them as such. 117 | 118 | An example of something I do often. 119 | 120 | ```powershell 121 | PS C:\Users\megan> $oktauser = oktaGetUserbyID -oOrg prev -uid mbegan@gmail.com 122 | [ GET https://varian.oktapreview.com/api/v1/users/mbegan@gmail.com ] 123 | 124 | PS C:\Users\megan> $groups = oktaGetGroupsbyUserId -oOrg prev -uid $oktauser.id 125 | [ GET https://varian.oktapreview.com/api/v1/users/00u3j3jj2cLstvJL70h7/groups ] 126 | 127 | PS C:\Users\megan> foreach ($group in $groups) {write-host $group.profile.name $group.id} 128 | Everyone 00g326179lGHZOYPWXCD 129 | okta.throwaway 00g3hyrge0QfpnvM80h7 130 | 131 | PS C:\Users\megan> oktaDeleteUserfromGroup -oOrg prev -uid $oktauser.id -gid $groups[1].id 132 | [ DELETE https://varian.oktapreview.com/api/v1/groups/00g3hyrge0QfpnvM80h7/users/00u3j3jj2cLstvJL70h7 ] 133 | ``` 134 | 135 | Some very basic examples, it can do much more. 136 | 137 | It supports pagination, so grabbing ALL of your users or groups is not a problem. 138 | 139 | I'll add more details on usage later, if you have a specific use case ask away i'll post an example. 140 | 141 | Also browse on over to [Okta community](https://support.okta.com/help/community) for more discussion 142 | 143 | ## A note about TLS 1.2 144 | 145 | Momentum is shifting to clients and servers supporting TLS 1.2. This plugin is capable of connecting to Okta with TLS 1.2 but doesn't do anything to direct the protocol used rather it relies on the SystemDefault configured for [schannel on the host](https://msdn.microsoft.com/en-us/library/system.net.securityprotocoltype(v=vs.110).aspx) 146 | 147 | If you want to force TLS 1.2 make sure your system can actually [support it](https://blogs.perficient.com/microsoft/2016/04/tsl-1-2-and-net-support/). 148 | 149 | ### force TLS 1.2 150 | 151 | If you decide you want to force this module to use TLS1.2 add this code block to your Okta_org.ps1 or your $PROFILE script. 152 | 153 | ```powershell 154 | try 155 | { 156 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 157 | } 158 | catch 159 | { 160 | Write-Warning $_.Exception.Message 161 | } 162 | ``` 163 | 164 | #### Available Commands 165 | 166 | - oktaActivateUserbyId 167 | - oktaAddRoleTargetsByUserId 168 | - oktaAddUseridtoGroupid 169 | - oktaAddUsertoRoles 170 | - oktaAdminExpirePasswordbyID 171 | - oktaAdminUpdatePasswordbyID 172 | - oktaAdminUpdateQandAbyID 173 | - oktaAuthnQuestionWithState 174 | - oktaChangePasswordbyID 175 | - oktaChangeProfilebyID 176 | - oktaCheckCreds 177 | - oktaCheckCredsOld 178 | - oktaConvertGroupbyId 179 | - oktaConverttoSecureString 180 | - oktaConvertUsertoFederation 181 | - oktaDeactivateUserbyID 182 | - oktaDeleteGroupbyId 183 | - oktaDeleteUserfromGroup 184 | - oktaDelRoleTargetsByUserId 185 | - oktaDelUserFromAllGroups 186 | - oktaDelUseridfromAppid 187 | - oktaDelUseridfromGroupid 188 | - oktaExternalIdtoGUID 189 | - oktaForgotPasswordbyId 190 | - oktaGetActiveApps 191 | - oktaGetAppbyId 192 | - oktaGetAppGroups 193 | - oktaGetAppLinksbyUserId 194 | - oktaGetAppProfilebyUserId 195 | - oktaGetAppsbyUserId 196 | - oktaGetFactorbyUser 197 | - oktaGetFactorsbyUser 198 | - oktaGetGroupbyId 199 | - oktaGetGroupMembersbyId 200 | - oktaGetGroupsAll 201 | - oktaGetGroupsbyquery 202 | - oktaGetGroupsbyUserId 203 | - oktaGetMasterProfile 204 | - oktaGetprofilebyId 205 | - oktaGetProfileMappingBySchema 206 | - oktaGetRolesByUserId 207 | - oktaGetSchemabyID 208 | - oktaGetTypebyID 209 | - oktaGetTypes 210 | - oktaGetUserbyID 211 | - oktaGetUsersbyAppID 212 | - oktaGetUserSchemabyType 213 | - oktaListActiveUsers 214 | - oktaListDeprovisionedUsers 215 | - oktaListUsers 216 | - oktaListUsersbyAttribute 217 | - oktaListUsersbyDate 218 | - oktaListUsersbyStatus 219 | - oktaNewPassword 220 | - oktaNewUser 221 | - oktaProcessHeaderLink 222 | - oktaPutProfileupdate 223 | - oktaResetFactorbyUser 224 | - oktaResetFactorsbyUser 225 | - oktaResetPasswordbyID 226 | - oktaSetAppidCredentialUsername 227 | - oktaUnlockUserbyId 228 | - oktaUpdateApp 229 | - oktaUpdateAppExternalIdbyUserId 230 | - oktaUpdateAppProfilebyUserId 231 | - oktaUpdateUserbyID 232 | - oktaUpdateUserProfilebyID 233 | - oktaVerifyMFAnswerbyUser 234 | - oktaVerifyOTPbyUser 235 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Matt Egan 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | Apache License 16 | Version 2.0, January 2004 17 | http://www.apache.org/licenses/ 18 | 19 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 20 | 21 | 1. Definitions. 22 | 23 | "License" shall mean the terms and conditions for use, reproduction, 24 | and distribution as defined by Sections 1 through 9 of this document. 25 | 26 | "Licensor" shall mean the copyright owner or entity authorized by 27 | the copyright owner that is granting the License. 28 | 29 | "Legal Entity" shall mean the union of the acting entity and all 30 | other entities that control, are controlled by, or are under common 31 | control with that entity. For the purposes of this definition, 32 | "control" means (i) the power, direct or indirect, to cause the 33 | direction or management of such entity, whether by contract or 34 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 35 | outstanding shares, or (iii) beneficial ownership of such entity. 36 | 37 | "You" (or "Your") shall mean an individual or Legal Entity 38 | exercising permissions granted by this License. 39 | 40 | "Source" form shall mean the preferred form for making modifications, 41 | including but not limited to software source code, documentation 42 | source, and configuration files. 43 | 44 | "Object" form shall mean any form resulting from mechanical 45 | transformation or translation of a Source form, including but 46 | not limited to compiled object code, generated documentation, 47 | and conversions to other media types. 48 | 49 | "Work" shall mean the work of authorship, whether in Source or 50 | Object form, made available under the License, as indicated by a 51 | copyright notice that is included in or attached to the work 52 | (an example is provided in the Appendix below). 53 | 54 | "Derivative Works" shall mean any work, whether in Source or Object 55 | form, that is based on (or derived from) the Work and for which the 56 | editorial revisions, annotations, elaborations, or other modifications 57 | represent, as a whole, an original work of authorship. For the purposes 58 | of this License, Derivative Works shall not include works that remain 59 | separable from, or merely link (or bind by name) to the interfaces of, 60 | the Work and Derivative Works thereof. 61 | 62 | "Contribution" shall mean any work of authorship, including 63 | the original version of the Work and any modifications or additions 64 | to that Work or Derivative Works thereof, that is intentionally 65 | submitted to Licensor for inclusion in the Work by the copyright owner 66 | or by an individual or Legal Entity authorized to submit on behalf of 67 | the copyright owner. For the purposes of this definition, "submitted" 68 | means any form of electronic, verbal, or written communication sent 69 | to the Licensor or its representatives, including but not limited to 70 | communication on electronic mailing lists, source code control systems, 71 | and issue tracking systems that are managed by, or on behalf of, the 72 | Licensor for the purpose of discussing and improving the Work, but 73 | excluding communication that is conspicuously marked or otherwise 74 | designated in writing by the copyright owner as "Not a Contribution." 75 | 76 | "Contributor" shall mean Licensor and any individual or Legal Entity 77 | on behalf of whom a Contribution has been received by Licensor and 78 | subsequently incorporated within the Work. 79 | 80 | 2. Grant of Copyright License. Subject to the terms and conditions of 81 | this License, each Contributor hereby grants to You a perpetual, 82 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 83 | copyright license to reproduce, prepare Derivative Works of, 84 | publicly display, publicly perform, sublicense, and distribute the 85 | Work and such Derivative Works in Source or Object form. 86 | 87 | 3. Grant of Patent License. Subject to the terms and conditions of 88 | this License, each Contributor hereby grants to You a perpetual, 89 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 90 | (except as stated in this section) patent license to make, have made, 91 | use, offer to sell, sell, import, and otherwise transfer the Work, 92 | where such license applies only to those patent claims licensable 93 | by such Contributor that are necessarily infringed by their 94 | Contribution(s) alone or by combination of their Contribution(s) 95 | with the Work to which such Contribution(s) was submitted. If You 96 | institute patent litigation against any entity (including a 97 | cross-claim or counterclaim in a lawsuit) alleging that the Work 98 | or a Contribution incorporated within the Work constitutes direct 99 | or contributory patent infringement, then any patent licenses 100 | granted to You under this License for that Work shall terminate 101 | as of the date such litigation is filed. 102 | 103 | 4. Redistribution. You may reproduce and distribute copies of the 104 | Work or Derivative Works thereof in any medium, with or without 105 | modifications, and in Source or Object form, provided that You 106 | meet the following conditions: 107 | 108 | (a) You must give any other recipients of the Work or 109 | Derivative Works a copy of this License; and 110 | 111 | (b) You must cause any modified files to carry prominent notices 112 | stating that You changed the files; and 113 | 114 | (c) You must retain, in the Source form of any Derivative Works 115 | that You distribute, all copyright, patent, trademark, and 116 | attribution notices from the Source form of the Work, 117 | excluding those notices that do not pertain to any part of 118 | the Derivative Works; and 119 | 120 | (d) If the Work includes a "NOTICE" text file as part of its 121 | distribution, then any Derivative Works that You distribute must 122 | include a readable copy of the attribution notices contained 123 | within such NOTICE file, excluding those notices that do not 124 | pertain to any part of the Derivative Works, in at least one 125 | of the following places: within a NOTICE text file distributed 126 | as part of the Derivative Works; within the Source form or 127 | documentation, if provided along with the Derivative Works; or, 128 | within a display generated by the Derivative Works, if and 129 | wherever such third-party notices normally appear. The contents 130 | of the NOTICE file are for informational purposes only and 131 | do not modify the License. You may add Your own attribution 132 | notices within Derivative Works that You distribute, alongside 133 | or as an addendum to the NOTICE text from the Work, provided 134 | that such additional attribution notices cannot be construed 135 | as modifying the License. 136 | 137 | You may add Your own copyright statement to Your modifications and 138 | may provide additional or different license terms and conditions 139 | for use, reproduction, or distribution of Your modifications, or 140 | for any such Derivative Works as a whole, provided Your use, 141 | reproduction, and distribution of the Work otherwise complies with 142 | the conditions stated in this License. 143 | 144 | 5. Submission of Contributions. Unless You explicitly state otherwise, 145 | any Contribution intentionally submitted for inclusion in the Work 146 | by You to the Licensor shall be under the terms and conditions of 147 | this License, without any additional terms or conditions. 148 | Notwithstanding the above, nothing herein shall supersede or modify 149 | the terms of any separate license agreement you may have executed 150 | with Licensor regarding such Contributions. 151 | 152 | 6. Trademarks. This License does not grant permission to use the trade 153 | names, trademarks, service marks, or product names of the Licensor, 154 | except as required for reasonable and customary use in describing the 155 | origin of the Work and reproducing the content of the NOTICE file. 156 | 157 | 7. Disclaimer of Warranty. Unless required by applicable law or 158 | agreed to in writing, Licensor provides the Work (and each 159 | Contributor provides its Contributions) on an "AS IS" BASIS, 160 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 161 | implied, including, without limitation, any warranties or conditions 162 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 163 | PARTICULAR PURPOSE. You are solely responsible for determining the 164 | appropriateness of using or redistributing the Work and assume any 165 | risks associated with Your exercise of permissions under this License. 166 | 167 | 8. Limitation of Liability. In no event and under no legal theory, 168 | whether in tort (including negligence), contract, or otherwise, 169 | unless required by applicable law (such as deliberate and grossly 170 | negligent acts) or agreed to in writing, shall any Contributor be 171 | liable to You for damages, including any direct, indirect, special, 172 | incidental, or consequential damages of any character arising as a 173 | result of this License or out of the use or inability to use the 174 | Work (including but not limited to damages for loss of goodwill, 175 | work stoppage, computer failure or malfunction, or any and all 176 | other commercial damages or losses), even if such Contributor 177 | has been advised of the possibility of such damages. 178 | 179 | 9. Accepting Warranty or Additional Liability. While redistributing 180 | the Work or Derivative Works thereof, You may choose to offer, 181 | and charge a fee for, acceptance of support, warranty, indemnity, 182 | or other liability obligations and/or rights consistent with this 183 | License. However, in accepting such obligations, You may act only 184 | on Your own behalf and on Your sole responsibility, not on behalf 185 | of any other Contributor, and only if You agree to indemnify, 186 | defend, and hold each Contributor harmless for any liability 187 | incurred by, or claims asserted against, such Contributor by reason 188 | of your accepting any such warranty or additional liability. 189 | 190 | END OF TERMS AND CONDITIONS 191 | -------------------------------------------------------------------------------- /Okta.psm1: -------------------------------------------------------------------------------- 1 | $ExecutionContext.SessionState.Module.OnRemove = { 2 | Remove-Module Okta_org 3 | } 4 | 5 | function _oktaThrowError() 6 | { 7 | param 8 | ( 9 | [parameter(Mandatory=$true)][String]$text 10 | ) 11 | 12 | try 13 | { 14 | $OktaSays = ConvertFrom-Json -InputObject $text 15 | } 16 | catch 17 | { 18 | throw $text 19 | } 20 | <# Can't decide what to throw here... #> 21 | <# Highly subject to change... #> 22 | if ($OktaSays.errorCauses[0].errorSummary) 23 | { 24 | $formatError = New-Object System.FormatException -ArgumentList ($OktaSays.errorCode + " ; " + $OktaSays.errorCauses[0].errorSummary) 25 | } else { 26 | $formatError = New-Object System.FormatException -ArgumentList ($OktaSays.errorCode + " ; " + $OktaSays.errorSummary) 27 | } 28 | #@@@ too bad this doesn't actually work 29 | $formatError.HelpLink = $text 30 | $formatError.Source = $Error[0].Exception 31 | throw $formatError 32 | } 33 | 34 | function oktaNewPassword 35 | { 36 | param 37 | ( 38 | [Int32]$Length = 15, 39 | [Int32]$MustIncludeSets = 3 40 | ) 41 | 42 | $CharacterSets = @("ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwzyz","0123456789","!$-#") 43 | 44 | $Random = New-Object Random 45 | 46 | $Password = "" 47 | $IncludedSets = "" 48 | $IsNotComplex = $true 49 | while ($IsNotComplex -or $Password.Length -lt $Length) 50 | { 51 | $Set = $Random.Next(0, 4) 52 | if (!($IsNotComplex -and $IncludedSets -match "$Set" -And $Password.Length -lt ($Length - $IncludedSets.Length))) 53 | { 54 | if ($IncludedSets -notmatch "$Set") 55 | { 56 | $IncludedSets = "$IncludedSets$Set" 57 | } 58 | if ($IncludedSets.Length -ge $MustIncludeSets) 59 | { 60 | $IsNotcomplex = $false 61 | } 62 | 63 | $Password = "$Password$($CharacterSets[$Set].SubString($Random.Next(0, $CharacterSets[$Set].Length), 1))" 64 | } 65 | } 66 | return $Password 67 | } 68 | 69 | function oktaRandLower 70 | { 71 | param 72 | ( 73 | [Int32]$Length = 18, 74 | [Int32]$MustIncludeSets = 3 75 | ) 76 | 77 | $CharacterSets = @("abcdefghijklmnopqrstuvwzyz","abcdefghijklmnopqrstuvwzyz","abcdefghijklmnopqrstuvwzyz","abcdefghijklmnopqrstuvwzyz") 78 | 79 | $Random = New-Object Random 80 | 81 | $Password = "" 82 | $IncludedSets = "" 83 | $IsNotComplex = $true 84 | while ($IsNotComplex -or $Password.Length -lt $Length) 85 | { 86 | $Set = $Random.Next(0, 4) 87 | if (!($IsNotComplex -and $IncludedSets -match "$Set" -And $Password.Length -lt ($Length - $IncludedSets.Length))) 88 | { 89 | if ($IncludedSets -notmatch "$Set") 90 | { 91 | $IncludedSets = "$IncludedSets$Set" 92 | } 93 | if ($IncludedSets.Length -ge $MustIncludeSets) 94 | { 95 | $IsNotcomplex = $false 96 | } 97 | 98 | $Password = "$Password$($CharacterSets[$Set].SubString($Random.Next(0, $CharacterSets[$Set].Length), 1))" 99 | } 100 | } 101 | return $Password 102 | } 103 | 104 | function oktaExternalIdtoGUID() 105 | { 106 | param 107 | ( 108 | [parameter(Mandatory=$true)][String]$externalId 109 | ) 110 | 111 | $bytes = [System.Convert]::FromBase64String($externalId) 112 | $guid = New-Object -TypeName System.Guid -ArgumentList(,$bytes) 113 | return $guid 114 | } 115 | 116 | function oktaConverttoSecureString() 117 | { 118 | param 119 | ( 120 | [string]$insecureString 121 | ) 122 | if ($insecureString) 123 | { 124 | $secureString = (ConvertFrom-SecureString -SecureString (ConvertTo-SecureString -AsPlainText -Force -String $insecureString)) 125 | } else { 126 | $secureString = (ConvertFrom-SecureString -SecureString (Read-Host -AsSecureString -Prompt "PlainText Secret Key")) 127 | } 128 | return $secureString 129 | } 130 | 131 | function oktaProcessHeaderLink() 132 | { 133 | param 134 | ( 135 | [Parameter(Mandatory=$true)]$linkHeader 136 | ) 137 | #may need to tweak to support windows and mac since they seem to have a different behavior here. 138 | if ($linkHeader -is [System.String[]]) 139 | { 140 | $links = $linkHeader 141 | } elseif ($linkHeader -is [System.String]) 142 | { 143 | $links = $linkHeader.Split(",") 144 | } 145 | 146 | Write-Verbose("we got header links! " + $links.Count + " of them actually") 147 | [HashTable]$olinks = @{} 148 | 149 | foreach ($link in $links) 150 | { 151 | #Yes I know it is a regex, but sometimes they work better 152 | if ($link.Trim() -match '^<(https://.+)>; rel="(\w+)"$') 153 | { 154 | $olinks.add($Matches[2].Trim(), $Matches[1].Trim()) 155 | } 156 | } 157 | return $olinks 158 | } 159 | 160 | function oktaMakeUserAgent() 161 | { 162 | if ($Global:defaultUserAgent) 163 | { 164 | return $Global:defaultUserAgent 165 | } 166 | 167 | if ($PSVersionTable.Contains("OS")) 168 | { 169 | $psOs = $PSVersionTable["OS"].ToString() 170 | } else { 171 | $psOs = "UnknownOS" 172 | } 173 | 174 | if ($PSVersionTable.Contains("Platform")) 175 | { 176 | $psPlatform = $PSVersionTable["Platform"].ToString() 177 | } else { 178 | $psPlatform = "UnknownPlatform" 179 | } 180 | 181 | if ($PSVersionTable.Contains("PSVersion")) 182 | { 183 | $psVer = $PSVersionTable["PSVersion"].ToString() 184 | } else { 185 | $psVer = "UnknownPsVer" 186 | } 187 | 188 | $module = Get-Module -Name Okta 189 | $modVer = $module.Version.ToString() 190 | 191 | $userAgent = "Okta-PSModule/" + $modVer + " (" + $psVer + ")" + " (" + $psPlatform + ")"+ " (" + $psOs + ")" 192 | Write-Verbose("Just Made this UserAgent: " + $userAgent) 193 | $Global:defaultUserAgent = $userAgent 194 | return $userAgent 195 | } 196 | 197 | function oktaBuildURIQuery() 198 | { 199 | param 200 | ( 201 | [parameter(Mandatory=$true)][UriBuilder]$uri, 202 | [parameter(Mandatory=$true)][Hashtable]$addParams 203 | ) 204 | 205 | foreach ($key in $addParams.Keys) 206 | { 207 | $addParam = $key + "=" + $addParams[$key] 208 | if ($uri.Query.Length -eq 0) 209 | { 210 | $uri.Query = $addParam 211 | } else { 212 | $uri.Query = $uri.Query.Substring(1) + "&" + $addParam 213 | } 214 | } 215 | return $uri 216 | } 217 | 218 | function oktaBuildURI() 219 | { 220 | param 221 | ( 222 | [parameter(Mandatory=$true)][string]$resource, 223 | [parameter(Mandatory=$true)][Hashtable]$params 224 | ) 225 | Write-Verbose("Start: " + $resource) 226 | $uri = [System.UriBuilder]::new("https", "hostplaceholder", 443, $resource) 227 | 228 | foreach ($key in $params.Keys) 229 | { 230 | $param = $key + "=" + $params[$key] 231 | if ($uri.Query.Length -eq 0) 232 | { 233 | $uri.Query = $param 234 | } else { 235 | $uri.Query = $uri.Query.Substring(1) + "&" + $param 236 | } 237 | } 238 | $newResource = ($uri.Path + $uri.Query) 239 | Write-Verbose("Before: " + $newResource) 240 | $newResource = [System.Web.HttpUtility]::UrlPathEncode($newResource) 241 | Write-Verbose(" After: " + $newResource) 242 | 243 | return $newResource 244 | } 245 | 246 | function _testOrg() 247 | { 248 | param 249 | ( 250 | [parameter(Mandatory=$true)][String]$org 251 | ) 252 | if ($oktaOrgs[$org]) 253 | { 254 | return $true 255 | } else { 256 | $estring = "The Org:" + $org + " is not defined in the Okta_org.ps1 file" 257 | throw $estring 258 | } 259 | } 260 | 261 | function OktaUserfromJson() 262 | { 263 | param 264 | ( 265 | $user 266 | ) 267 | 268 | $dateFields = ('created','activated','statusChanged','lastLogin','lastUpdated','passwordChanged') 269 | 270 | foreach ($df in $dateFields) 271 | { 272 | if ($user.$df) 273 | { 274 | $user.$df = Get-Date $user.$df 275 | } else { 276 | $user.$df = $null 277 | } 278 | } 279 | return $user 280 | } 281 | 282 | function OktaAppfromJson() 283 | { 284 | param 285 | ( 286 | $app 287 | ) 288 | 289 | $dateFields = ('created','lastUpdated') 290 | 291 | foreach ($df in $dateFields) 292 | { 293 | if ($app.$df) 294 | { 295 | $app.$df = Get-Date $app.$df 296 | } else { 297 | $app.$df = $null 298 | } 299 | } 300 | return $app 301 | } 302 | 303 | function OktaAppUserfromJson() 304 | { 305 | param 306 | ( 307 | $appUser, 308 | [parameter(Mandatory=$false)][switch]$skinny 309 | ) 310 | 311 | if ($skinny) 312 | { 313 | $dateFields = ('created','lastUpdated','statusChanged','passwordChanged') 314 | } else { 315 | $dateFields = ('created','lastUpdated','statusChanged','passwordChanged','lastSync') 316 | } 317 | 318 | foreach ($df in $dateFields) 319 | { 320 | if ($appUser.$df) 321 | { 322 | $appUser.$df = Get-Date $appUser.$df 323 | } else { 324 | $appUser.$df = $null 325 | } 326 | } 327 | return $appUser 328 | } 329 | 330 | function OktaRolefromJson() 331 | { 332 | param 333 | ( 334 | $role 335 | ) 336 | 337 | $dateFields = ('created','lastUpdated') 338 | 339 | foreach ($df in $dateFields) 340 | { 341 | if ($role[$df]) 342 | { 343 | $role[$df] = Get-Date $role.$df 344 | } else { 345 | $role[$df] = $null 346 | } 347 | } 348 | return $role 349 | } 350 | 351 | $okta_epoch = New-Object System.DateTime (1970, 1, 1, 0, 0, 0, [System.DateTimeKind]::Utc) 352 | function _oktaRateLimitTimeRemaining() 353 | { 354 | param 355 | ( 356 | [long]$seconds 357 | ) 358 | 359 | $reset = $okta_epoch.AddSeconds($seconds) 360 | $now = Get-Date 361 | $timeToReset = New-TimeSpan -Start ($now.ToUniversalTime()) -End $reset 362 | return $timeToReset.TotalSeconds 363 | } 364 | 365 | function _oktaRateLimitCheck() 366 | { 367 | #this needs some work... 368 | [double]$warn = .50 369 | [double]$throttle = .20 370 | #how many other calls per second should we assume are there for backoff calculations? 371 | [int]$cps = 16 372 | 373 | $remain = [int][string]$rateLimt.Remaining 374 | $limit = [int][string]$rateLimt.Limit 375 | $reset = [long][string]$rateLimt.Reset 376 | 377 | $used = ($remain / $limit) 378 | $usedpct = $used.ToString("P") 379 | $limit_note = "You have $remain out of $limit aka: $usedpct left in the tank" 380 | 381 | if ($remain -eq 0) 382 | { 383 | Write-Verbose("remain is 0") 384 | $remain = 1 385 | } 386 | 387 | if ($used -lt $warn) 388 | { 389 | $reset = _oktaRateLimitTimeRemaining -seconds $reset 390 | $limit_note = "You have $remain out of $limit aka: $used in the next $reset seconds" 391 | Write-Warning($limit_note) 392 | 393 | if ($used -lt $throttle) 394 | { 395 | if ($reset -lt 10) { $reset = 10 } 396 | # how aggressive should we sleep? same logic for now. 397 | if ( ($reset * $cps) -gt ($remain) ) 398 | { 399 | $aggr = "hard" 400 | $sleepTime = (( ($reset * $cps) / $remain) * 1000) 401 | } else { 402 | $aggr = "soft" 403 | $sleepTime = (( ($reset * $cps) / $remain) * 10) 404 | } 405 | 406 | if ($sleepTime -gt ($reset * 1000) ) 407 | { 408 | Write-Verbose ("Backoff on the sleep man!") 409 | $sleepTime = (($reset + 10) * 1000) 410 | } 411 | 412 | Write-Warning("Throttling " + $aggr + " for: " + $sleepTime + " milliseconds" ) 413 | Start-Sleep -Milliseconds $sleepTime 414 | } 415 | 416 | } else { 417 | Write-Verbose($limit_note) 418 | } 419 | } 420 | 421 | $resHeaders = @( 422 | "X-Okta-Request-Id", 423 | "X-Rate-Limit-Limit", 424 | "X-Rate-Limit-Remaining", 425 | "X-Rate-Limit-Reset", 426 | "Link", 427 | "Content-Length", 428 | "Content-Type", 429 | "Date" 430 | ) 431 | 432 | function _oktaMakeCall() 433 | { 434 | param 435 | ( 436 | [parameter(Mandatory=$true)][ValidateSet("Get", "Head", "Post", "Put", "Delete")][String]$method, 437 | [parameter(Mandatory=$true)][String]$uri, 438 | [parameter(Mandatory=$true)][hashtable]$headers, 439 | [parameter(Mandatory=$false)][Object]$body = @{}, 440 | [parameter(Mandatory=$false)][String]$userAgent, 441 | [parameter(Mandatory=$false)][String]$contentType = "application/json" 442 | ) 443 | 444 | if (!$userAgent) 445 | { 446 | $userAgent = oktaMakeUserAgent 447 | } 448 | 449 | <# Verbose Request header readout #> 450 | foreach ($h in $headers.Keys) 451 | { 452 | if ($h -eq 'Authorization') 453 | { 454 | Write-Verbose("Req-Hdr: " + $h + " -> SSWS xXxXxXxxXxxXxXxXxxXx") 455 | } else { 456 | Write-Verbose("Req-Hdr: " + $h + " -> " + $headers[$h]) 457 | } 458 | } 459 | Write-Verbose("Req-Hdr: " + "Content-Type" + " -> " + $contentType) 460 | Write-Verbose("Req-Hdr: " + "User-Agent" + " -> " + $userAgent) 461 | try 462 | { 463 | if (!$Global:myWebSession) 464 | { 465 | Write-Verbose("Creating myWebSession first") 466 | if ( ($method -eq "Post") -or ($method -eq "Put") ) 467 | { 468 | $postData = ConvertTo-Json $body -Depth 10 469 | Write-Verbose($postData) 470 | $request2 = Invoke-WebRequest -Uri $uri -Method $method -UserAgent $userAgent -Headers $headers ` 471 | -ContentType $contentType -Verbose:$oktaVerbose -Body $postData -ErrorVariable evar -SessionVariable Global:myWebSession 472 | } else { 473 | $request2 = Invoke-WebRequest -Uri $uri -Method $method -UserAgent $userAgent -Headers $headers ` 474 | -ContentType $contentType -Verbose:$oktaVerbose -ErrorVariable evar -SessionVariable Global:myWebSession 475 | } 476 | } else { 477 | if ( ($method -eq "Post") -or ($method -eq "Put") ) 478 | { 479 | $postData = ConvertTo-Json $body -Depth 10 480 | Write-Verbose($postData) 481 | $request2 = Invoke-WebRequest -Uri $uri -Method $method -UserAgent $userAgent -Headers $headers ` 482 | -ContentType $contentType -Verbose:$oktaVerbose -Body $postData -ErrorVariable evar -WebSession $Global:myWebSession 483 | } else { 484 | $request2 = Invoke-WebRequest -Uri $uri -Method $method -UserAgent $userAgent -Headers $headers ` 485 | -ContentType $contentType -Verbose:$oktaVerbose -ErrorVariable evar -WebSession $Global:myWebSession 486 | } 487 | } 488 | } 489 | catch [System.Net.WebException], [Microsoft.PowerShell.Commands.HttpResponseException] 490 | { 491 | 492 | $code = $_.Exception.Response.StatusCode 493 | 494 | if ( $_.Exception.Response.Headers.Contains('X-Okta-Requst-Id') ) 495 | { 496 | $reqId = $_.Exception.Response.Headers.GetValues('X-Okta-Requst-Id') 497 | Write-Warning("Okta Request ID: " + $reqId[0]) 498 | } 499 | 500 | if ($_.ErrorDetails.Message) 501 | { 502 | try 503 | { 504 | $oktaException = ConvertFrom-Json -InputObject $_.ErrorDetails.Message 505 | } 506 | catch { 507 | $oktaException = $false 508 | } 509 | if ($oktaException) 510 | { 511 | $oktaMessage = "`nerrorCode: " + $oktaException.errorCode 512 | $oktaMessage += "; errorSummary: " + $oktaException.errorSummary 513 | $oktaMessage += "; errorId: " + $oktaException.errorId 514 | $oktaMessage += "`n`tcauses:`n" 515 | foreach ($cause in $oktaException.errorCauses) 516 | { 517 | $oktaMessage += "`t`t" + $cause.errorSummary + "`n" 518 | } 519 | Write-Error($oktaMessage) 520 | } else { 521 | Write-Error($_.ErrorDetails.Message.ToString()) 522 | } 523 | } 524 | 525 | switch ($code) 526 | { 527 | "429" 528 | { 529 | Write-Warning("You hit the rate limit!") 530 | } 531 | "BadRequest" 532 | { 533 | Write-Warning("Your request was bad!") 534 | #Write-Warning($_.ErrorDetails.Message) 535 | throw($evar[0].ErrorRecord.Exception.Message) 536 | } 537 | "NotFound" 538 | { 539 | Write-Warning("Your item wasn't found!") 540 | throw($evar[0].ErrorRecord.Exception.Message) 541 | } 542 | "Forbidden" 543 | { 544 | Write-Warning("Your item was forbidden!") 545 | throw($evar[0].ErrorRecord.Exception.Message) 546 | } 547 | default 548 | { 549 | #Write-Warning("Okta RequestID: " + $_.Exception.Response.Headers['X-Okta-Request-Id']) 550 | Write-Warning($evar[0].ErrorRecord.Exception.GetType().FullName + " : " + $code) 551 | throw($evar[0].ErrorRecord.Exception.Message) 552 | } 553 | } 554 | } 555 | catch 556 | { 557 | Write-Warning("Catchall:" + $_.Exception.GetType().FullName + " : " + $_.Exception.Message ) 558 | throw($_.Exception.Message) 559 | } 560 | 561 | #Process Response Headers, debug, pagination and rate limiting 562 | if ( $request2 ) 563 | { 564 | $responseHeaders = $request2.Headers 565 | foreach ($rh in $responseHeaders.keys) 566 | { 567 | if ($resHeaders.Contains($rh)) 568 | { 569 | Write-Verbose("Res-Hdr: " + $rh + " -> " + $responseHeaders[$rh]) 570 | } 571 | } 572 | } 573 | 574 | if ($responseHeaders['X-Okta-Request-Id']) 575 | { 576 | Write-Verbose( "Okta Request ID: " + $responseHeaders['X-Okta-Request-Id'] ) 577 | } 578 | 579 | if ($responseHeaders['link']) 580 | { 581 | try 582 | { 583 | $link = oktaProcessHeaderLink -linkHeader $responseHeaders['link'] 584 | } 585 | catch 586 | { 587 | Write-Warning($_.Exception.Message) 588 | $link = $false 589 | } 590 | if ($link.next) 591 | { 592 | $next = $link.next 593 | } else { 594 | Write-Verbose("we had a link header, it didn't contain a next link though") 595 | $next = $false 596 | } 597 | Remove-Variable -Name link -Force 598 | } else { 599 | $next = $false 600 | } 601 | 602 | if ( $responseHeaders['X-Rate-Limit-Remaining'] ) 603 | { 604 | $rateLimt = @{ Reset = $responseHeaders['X-Rate-Limit-Reset'] 605 | Limit = $responseHeaders['X-Rate-Limit-Limit'] 606 | Remaining = $responseHeaders['X-Rate-Limit-Remaining'] 607 | } 608 | } else { 609 | $rateLimt = $false 610 | } 611 | 612 | if ($request2) 613 | { 614 | if ($request2.Content) 615 | { 616 | Write-Verbose("There was content retured, convert from json string") 617 | try 618 | { 619 | $result = ConvertFrom-Json -InputObject $request2.Content -Verbose:$oktaVerbose 620 | } 621 | catch 622 | { 623 | Write-Warning($_.Exception.Message) 624 | $result = $() 625 | $next = $false 626 | } 627 | } else { 628 | Write-Verbose("There was content retured, don't try to convert it") 629 | $result = $() 630 | $next = $false 631 | } 632 | } else { 633 | $result = $() 634 | } 635 | 636 | if ($rateLimt){ _oktaRateLimitCheck } 637 | 638 | return @{ result = $result ; next = $next ; ratelimit = $rateLimt } 639 | } 640 | 641 | function _oktaNewCall() 642 | { 643 | param 644 | ( 645 | [parameter(Mandatory=$true)][ValidateScript({_testOrg -org $_})][String]$oOrg, 646 | [parameter(Mandatory=$true)][ValidateSet("Get", "Head", "Post", "Put", "Delete")][String]$method, 647 | [parameter(Mandatory=$true)][String]$resource, 648 | [parameter(Mandatory=$false)][Object]$body = @{}, 649 | [parameter(Mandatory=$false)][boolean]$enablePagination = $OktaOrgs[$oOrg].enablePagination, 650 | [parameter(Mandatory=$false)][Object]$altHeaders, 651 | [parameter(Mandatory=$false)][ValidateRange(1,10000)][int]$limit, 652 | [parameter(Mandatory=$false)][boolean]$untrusted=$false, 653 | [parameter(Mandatory=$false)][String]$contentType = "application/json" 654 | ) 655 | 656 | $headers = New-Object System.Collections.Hashtable 657 | if (!$untrusted) 658 | { 659 | if ($OktaOrgs[$oOrg].encToken) 660 | { 661 | $_c = $headers.add('Authorization',('SSWS ' + ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR( (ConvertTo-SecureString -string ($OktaOrgs[$oOrg].encToken).ToString()) ) )))) 662 | } else { 663 | $_c = $headers.add('Authorization',('SSWS ' + ($OktaOrgs[$oOrg].secToken).ToString()) ) 664 | } 665 | } 666 | $_c = $headers.add('Accept-Charset','ISO-8859-1,utf-8') 667 | $_c = $headers.add('Accept-Language','en-US') 668 | $_c = $headers.add('Accept-Encoding','deflate,gzip') 669 | 670 | if ($resource -like 'https://*') 671 | { 672 | [string]$uri = $resource 673 | } else { 674 | [string]$uri = ($OktaOrgs[$oOrg].baseUrl).ToString() + $resource 675 | } 676 | #if our altHeaders contains an alternative UserAgent string set it 677 | if ( ($altHeaders) -and ($altHeaders['UserAgent']) ) 678 | { 679 | $userAgent = $altHeaders['UserAgent'] 680 | $altHeaders.Remove('UserAgent') 681 | } 682 | 683 | foreach ($alt in $altHeaders.Keys) 684 | { 685 | $_c = $headers.Add($alt,$altHeaders[$alt]) 686 | } 687 | 688 | <# 689 | .ratelimit = ratelimit headers or false 690 | .next = a link or false 691 | .result = psobject 692 | #> 693 | $getPages = $true 694 | [object]$results = @() 695 | $Global:nextNext = $false 696 | $next = $false 697 | 698 | while ($getPages) 699 | { 700 | try 701 | { 702 | if ($file) 703 | { 704 | $response = _oktaMakeCall -method $method -uri $uri -headers $headers -file $file -userAgent $userAgent -contentType $contentType 705 | } else { 706 | $response = _oktaMakeCall -method $method -uri $uri -headers $headers -body $body -userAgent $userAgent -contentType $contentType 707 | } 708 | } 709 | catch 710 | { 711 | Write-Warning($_.Exception.Message) 712 | Write-Warning("Encountered error, returning limited or empty set") 713 | $response=$false 714 | } 715 | 716 | if ($response) 717 | { 718 | $results += $response.result 719 | $next = $response.next 720 | if ($response.result -is [array]) 721 | { 722 | $i_count = $response.result.Count 723 | } else { 724 | $i_count = 1 725 | } 726 | 727 | } else { 728 | $i_count = 0 729 | $next = $false 730 | } 731 | 732 | Remove-Variable -Name response -Force 733 | 734 | $r_count = $results.Count 735 | Write-Verbose("This Page returned: " + $i_count + ", we've seen: " + $r_count + " results so far") 736 | 737 | if ($i_count -eq 0) 738 | { 739 | Write-Verbose("0 results returned, i predict an empty page coming up, lets skip it") 740 | #there nothing was returned, if there is a next link it is empty, if there isn't a nextlink assume the last link is the next link 741 | $getPages = $false 742 | if ($next) { $Global:nextNext = $next } else { $Global:nextNext = $uri } 743 | } 744 | 745 | if ($limit) 746 | { 747 | Write-Verbose("We have a limit: " + $limit + " so we'll predict and avoid empty pages") 748 | if ($i_count -lt $limit) #this would include 0 749 | { 750 | Write-Verbose("The number returned: " + $i_count + ", is less than the limit: " + $limit) 751 | $getPages = $false 752 | if ($next) { $Global:nextNext = $next } else { $Global:nextNext = $uri } 753 | } 754 | } 755 | if (! $enablePagination) 756 | { 757 | $getPages = $false 758 | } 759 | 760 | if ($next) 761 | { 762 | if ($getPages) 763 | { 764 | Write-Verbose("We see a valid next link of: " + $next) 765 | $uri = $next 766 | } else { 767 | Write-Verbose("We are not going to fetch the next link of: " + $next) 768 | } 769 | } else { 770 | Write-Verbose("We see no or an invalid next link of: " + $next.ToString()) 771 | $getPages = $false 772 | } 773 | 774 | } #End While 775 | 776 | return $results 777 | } 778 | 779 | function oktaNewUser() 780 | { 781 | param 782 | ( 783 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 784 | [string]$login, 785 | [string]$password, 786 | [string]$email, 787 | [string]$firstName, 788 | [string]$lastName, 789 | [string]$r_question="What Was your password?", 790 | [string]$r_answer=(oktaNewPassword), 791 | [array]$groupIds, 792 | [object]$additional=@{} 793 | ) 794 | $psobj = @{ 795 | profile = @{ 796 | firstName = $firstName 797 | lastName = $lastName 798 | email = $email 799 | login = $login 800 | } 801 | credentials = @{ 802 | password = @{ value = $password } 803 | recovery_question = @{ question = $r_question;answer = $r_answer.ToLower().Replace(" ","")} 804 | } 805 | } 806 | foreach ($attrib in $additional.keys) 807 | { 808 | $psobj.profile.add($attrib, $additional.$attrib) 809 | } 810 | if ($groupIds) 811 | { 812 | $psobj.add("groupIds", $groupIds) 813 | } 814 | [string]$method = "Post" 815 | [string]$resource = "/api/v1/users?activate=True" 816 | try 817 | { 818 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 819 | } 820 | catch 821 | { 822 | if ($oktaVerbose -eq $true) 823 | { 824 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 825 | } 826 | throw $_ 827 | } 828 | foreach ($user in $request) 829 | { 830 | $user = OktaUserfromJson -user $user 831 | } 832 | return $request 833 | } 834 | 835 | function oktaNewUser2() 836 | { 837 | param 838 | ( 839 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 840 | [parameter(Mandatory=$true)][string]$login, 841 | [parameter(Mandatory=$false)][string]$email, 842 | [parameter(Mandatory=$true)][string]$firstName, 843 | [parameter(Mandatory=$true)][string]$lastName, 844 | [parameter(Mandatory=$true)][string]$mobilePhone, 845 | [parameter(Mandatory=$false)][object]$additional=@{} 846 | ) 847 | if (!$email){$email=$login} 848 | $psobj = @{ 849 | profile = @{ 850 | firstName = $firstName 851 | lastName = $lastName 852 | email = $email 853 | login = $login 854 | mobilePhone = $mobilePhone 855 | } 856 | } 857 | foreach ($attrib in $additional.keys) 858 | { 859 | $psobj.profile.add($attrib, $additional.$attrib) 860 | } 861 | [string]$method = "Post" 862 | [string]$resource = "/api/v1/users?activate=False" 863 | try 864 | { 865 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 866 | } 867 | catch 868 | { 869 | if ($oktaVerbose -eq $true) 870 | { 871 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 872 | } 873 | throw $_ 874 | } 875 | foreach ($user in $request) 876 | { 877 | $user = OktaUserfromJson -user $user 878 | } 879 | return $request 880 | } 881 | 882 | function oktaChangeProfilebyID() 883 | { 884 | param 885 | ( 886 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 887 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 888 | [Parameter(Mandatory=$true)][hashtable]$newprofile 889 | ) 890 | 891 | $psobj = $newprofile 892 | 893 | [string]$method = "Put" 894 | [string]$resource = "/api/v1/users/" + $uid 895 | try 896 | { 897 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 898 | } 899 | catch 900 | { 901 | if ($oktaVerbose -eq $true) 902 | { 903 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 904 | } 905 | throw $_ 906 | } 907 | foreach ($user in $request) 908 | { 909 | $user = OktaUserfromJson -user $user 910 | } 911 | return $request 912 | } 913 | 914 | function oktaPutProfileupdate() 915 | { 916 | param 917 | ( 918 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 919 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 920 | [object]$updates 921 | ) 922 | 923 | $psobj = New-Object System.Collections.Hashtable 924 | Add-Member -InputObject $psobj -MemberType NoteProperty -Name profile -Value $updates 925 | 926 | [string]$method = "Put" 927 | [string]$resource = "/api/v1/users/" + $uid 928 | try 929 | { 930 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 931 | } 932 | catch 933 | { 934 | if ($oktaVerbose -eq $true) 935 | { 936 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 937 | } 938 | throw $_ 939 | } 940 | foreach ($user in $request) 941 | { 942 | $user = OktaUserfromJson -user $user 943 | } 944 | return $request 945 | } 946 | 947 | function oktaUpdateUserbyID() 948 | { 949 | param 950 | ( 951 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 952 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 953 | [string]$login, 954 | [string]$password, 955 | [string]$email, 956 | [string]$firstName, 957 | [string]$lastName, 958 | [string]$mobilePhone, 959 | [string]$r_question, 960 | [string]$r_answer 961 | ) 962 | $psobj = @{ 963 | "profile" = @{ 964 | "firstName" = $firstName 965 | "lastName" = $lastName 966 | "email" = $email 967 | "login" = $login 968 | "mobilePhone" = $mobilePhone 969 | } 970 | "credentials" = @{ 971 | "password" = @{ "value" = $password } 972 | "recovery_question" = @{ "question" = $r_question;"answer" = $r_answer.ToLower().Replace(" ","")} 973 | } 974 | } 975 | 976 | [string]$method = "Put" 977 | [string]$resource = "/api/v1/users/" + $uid 978 | try 979 | { 980 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 981 | } 982 | catch 983 | { 984 | if ($oktaVerbose -eq $true) 985 | { 986 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 987 | } 988 | throw $_ 989 | } 990 | foreach ($user in $request) 991 | { 992 | $user = OktaUserfromJson -user $user 993 | } 994 | return $request 995 | } 996 | 997 | function oktaChangePasswordbyID() 998 | { 999 | param 1000 | ( 1001 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1002 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 1003 | [string]$new_password, 1004 | [string]$old_password 1005 | ) 1006 | $psobj = @{ 1007 | "oldPassword" = @{ "value" = $old_password } 1008 | "newPassword" = @{ "value" = $new_password } 1009 | } 1010 | 1011 | [string]$method = "Post" 1012 | [string]$resource = "/api/v1/users/" + $uid + "/credentials/change_password" 1013 | try 1014 | { 1015 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 1016 | } 1017 | catch 1018 | { 1019 | if ($oktaVerbose -eq $true) 1020 | { 1021 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1022 | } 1023 | throw $_ 1024 | } 1025 | foreach ($user in $request) 1026 | { 1027 | $user = OktaUserfromJson -user $user 1028 | } 1029 | return $request 1030 | } 1031 | 1032 | function oktaAdminExpirePasswordbyID() 1033 | { 1034 | param 1035 | ( 1036 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1037 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 1038 | [string]$tempPassword=(oktaNewPassword) 1039 | ) 1040 | $psobj = @{ "tempPassword" = $tempPassword } 1041 | 1042 | [string]$method = "Post" 1043 | [string]$resource = "/api/v1/users/" + $uid + "/lifecycle/expire_password?tempPassword=false" 1044 | try 1045 | { 1046 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 1047 | } 1048 | catch 1049 | { 1050 | if ($oktaVerbose -eq $true) 1051 | { 1052 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1053 | } 1054 | throw $_ 1055 | } 1056 | foreach ($user in $request) 1057 | { 1058 | $user = OktaUserfromJson -user $user 1059 | } 1060 | return $request 1061 | } 1062 | 1063 | function oktaAdminUpdateQandAbyID() 1064 | { 1065 | param 1066 | ( 1067 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1068 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 1069 | [parameter(Mandatory=$true)][string]$question, 1070 | [parameter(Mandatory=$true)][string]$answer 1071 | ) 1072 | 1073 | $psobj = @{ 1074 | "credentials" = @{ 1075 | "recovery_question" = @{ "question" = $question; "answer" = $answer } 1076 | } 1077 | } 1078 | [string]$method = "Put" 1079 | [string]$resource = "/api/v1/users/" + $uid 1080 | try 1081 | { 1082 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 1083 | } 1084 | catch 1085 | { 1086 | if ($oktaVerbose -eq $true) 1087 | { 1088 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1089 | } 1090 | throw $_ 1091 | } 1092 | foreach ($user in $request) 1093 | { 1094 | $user = OktaUserfromJson -user $user 1095 | } 1096 | return $request 1097 | } 1098 | 1099 | function oktaAdminUpdatePasswordbyID() 1100 | { 1101 | param 1102 | ( 1103 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1104 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 1105 | [string]$password 1106 | ) 1107 | $psobj = @{ 1108 | "credentials" = @{ 1109 | "password" = @{ "value" = $password } 1110 | } 1111 | } 1112 | [string]$method = "Put" 1113 | [string]$resource = "/api/v1/users/" + $uid 1114 | try 1115 | { 1116 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 1117 | } 1118 | catch 1119 | { 1120 | if ($oktaVerbose -eq $true) 1121 | { 1122 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1123 | } 1124 | throw $_ 1125 | } 1126 | foreach ($user in $request) 1127 | { 1128 | $user = OktaUserfromJson -user $user 1129 | } 1130 | return $request 1131 | } 1132 | 1133 | function oktaForgotPasswordbyId() 1134 | { 1135 | param 1136 | ( 1137 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1138 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 1139 | [string]$r_answer, 1140 | [string]$new_password 1141 | ) 1142 | $psobj = @{ 1143 | "password" = @{ "value" = $new_password } 1144 | "recovery_question" = @{ "answer" = $r_answer.ToLower().Replace(" ","") } 1145 | } 1146 | [string]$method = "Post" 1147 | [string]$resource = "/api/v1/users/" + $uid + "/credentials/forgot_password" 1148 | try 1149 | { 1150 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 1151 | } 1152 | catch 1153 | { 1154 | if ($oktaVerbose -eq $true) 1155 | { 1156 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1157 | } 1158 | throw $_ 1159 | } 1160 | foreach ($user in $request) 1161 | { 1162 | $user = OktaUserfromJson -user $user 1163 | } 1164 | return $request 1165 | } 1166 | 1167 | function oktaCheckCredsOld() 1168 | { 1169 | <# 1170 | .Synopsis 1171 | Used to validate the credentials of a user against Okta 1172 | 1173 | .Description 1174 | Returns a One-Time token used to establish the users session with Okta. See: https://github.com/okta/api/blob/master/docs/endpoints/sessions.md#create-session 1175 | 1176 | .Parameter username 1177 | The users okta login value 1178 | 1179 | .Parameter password 1180 | the users plaintext password to be validated against okta 1181 | 1182 | .Parameter oOrg 1183 | the alias of the Okta Org (assuming everyone has more than one like I do) 1184 | 1185 | .Example 1186 | # Check credentials for mbe.gan@gmail.com against the prod okta org 1187 | oktaCheckCreds -oOrg 'prod' -username 'mbe.egan@gmail.com' -password 'Password2' 1188 | #> 1189 | 1190 | param 1191 | ( 1192 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1193 | [Parameter(Mandatory=$true)][string]$username, 1194 | [Parameter(Mandatory=$true)][string]$password 1195 | ) 1196 | 1197 | $request = $null 1198 | $psobj = @{ 1199 | "password" = $password 1200 | "username" = $username 1201 | } 1202 | [string]$method = "Post" 1203 | [string]$resource = "/api/v1/sessions?additionalFields=cookieToken" 1204 | try 1205 | { 1206 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 1207 | } 1208 | catch 1209 | { 1210 | if ($oktaVerbose -eq $true) 1211 | { 1212 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1213 | } 1214 | throw $_ 1215 | } 1216 | return $request 1217 | } 1218 | 1219 | function oktaCheckCreds() 1220 | { 1221 | <# 1222 | .Synopsis 1223 | Used to validate the credentials of a user against Okta 1224 | 1225 | .Description 1226 | Returns a One-Time token used to establish the users session with Okta. See: https://github.com/okta/api/blob/master/docs/endpoints/sessions.md#create-session 1227 | 1228 | .Parameter username 1229 | The users okta login value 1230 | 1231 | .Parameter password 1232 | the users plaintext password to be validated against okta 1233 | 1234 | .Parameter oOrg 1235 | the alias of the Okta Org (assuming everyone has more than one like I do) 1236 | 1237 | .Example 1238 | # Check credentials for mbe.gan@gmail.com against the prod okta org 1239 | oktaCheckCreds -oOrg 'prod' -username 'mbe.egan@gmail.com' -password 'Password2' 1240 | #> 1241 | 1242 | param 1243 | ( 1244 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1245 | [Parameter(Mandatory=$false)][string]$username, 1246 | [Parameter(Mandatory=$false)][string]$password, 1247 | [Parameter(Mandatory=$false)][string]$token, 1248 | [Parameter(Mandatory=$false)][string]$audience, 1249 | [Parameter(Mandatory=$false)][ValidateLength(1,2048)][string]$relayState, 1250 | [Parameter(Mandatory=$false)][switch]$multiOptionalFactorEnroll, 1251 | [Parameter(Mandatory=$false)][switch]$warnBeforePasswordExpired, 1252 | [Parameter(Mandatory=$false)][string]$UserAgent, 1253 | [Parameter(Mandatory=$false)][string]$ipAddress, 1254 | [Parameter(Mandatory=$false)][ValidateLength(1,32)][string]$deviceToken, 1255 | [Parameter(Mandatory=$false)][switch]$untrusted 1256 | ) 1257 | 1258 | [string]$method = "Post" 1259 | [string]$resource = "/api/v1/authn" 1260 | 1261 | if ($deviceToken) 1262 | { 1263 | $context = New-Object hashtable 1264 | $context.Add("deviceToken", $deviceToken) 1265 | } 1266 | 1267 | if ($multiOptionalFactorEnroll -or $warnBeforePasswordExpired) 1268 | { 1269 | [string[]]$param = "multiOptionalFactorEnroll","warnBeforePasswordExpired" 1270 | $options = New-Object hashtable 1271 | foreach ($p in $param) 1272 | { 1273 | if (Get-Variable -Name $p -ErrorAction SilentlyContinue) 1274 | { 1275 | if ((Get-Variable -Name $p -ValueOnly) -ne "") 1276 | { 1277 | $options.Add($p,(Get-Variable -Name $p -ValueOnly)) 1278 | } 1279 | } 1280 | } 1281 | } 1282 | 1283 | [string[]]$param = "username","password","audience","relayState","token","options","context" 1284 | $psobj = New-Object hashtable 1285 | foreach ($p in $param) 1286 | { 1287 | if (Get-Variable -Name $p -ErrorAction SilentlyContinue) 1288 | { 1289 | if ((Get-Variable -Name $p -ValueOnly) -ne "") 1290 | { 1291 | $psobj.Add($p,(Get-Variable -Name $p -ValueOnly)) 1292 | } 1293 | } 1294 | } 1295 | 1296 | $altHeaders = New-Object hashtable 1297 | if ($UserAgent) 1298 | { 1299 | $altHeaders.Add('UserAgent', $UserAgent) 1300 | } 1301 | if ($ipAddress) 1302 | { 1303 | $altHeaders.Add('X-Forwarded-For', $ipAddress) 1304 | } 1305 | 1306 | try 1307 | { 1308 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj -altHeaders $altHeaders -untrusted $untrusted 1309 | } 1310 | catch 1311 | { 1312 | if ($oktaVerbose -eq $true) 1313 | { 1314 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1315 | } 1316 | throw $_ 1317 | } 1318 | return $request 1319 | } 1320 | 1321 | function oktaGetUserbyID() 1322 | { 1323 | param 1324 | ( 1325 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1326 | [parameter(Mandatory=$true)][alias("uid")][ValidateLength(1,100)][String]$userName 1327 | ) 1328 | #UrlEncode 1329 | #$uid = [System.Web.HttpUtility]::UrlPathEncode($userName) 1330 | $uid = $userName 1331 | 1332 | [string]$method = "Get" 1333 | [string]$resource = "/api/v1/users/" + $uid 1334 | 1335 | try 1336 | { 1337 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 1338 | } 1339 | catch 1340 | { 1341 | if ($oktaVerbose -eq $true) 1342 | { 1343 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1344 | } 1345 | throw $_ 1346 | } 1347 | foreach ($user in $request) 1348 | { 1349 | $user = OktaUserfromJson -user $user 1350 | } 1351 | return $request 1352 | } 1353 | 1354 | function oktaDeleteUserbyID() 1355 | { 1356 | param 1357 | ( 1358 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1359 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid 1360 | ) 1361 | 1362 | [string]$method = "Delete" 1363 | [string]$resource = "/api/v1/users/" + $uid 1364 | 1365 | try 1366 | { 1367 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 1368 | } 1369 | catch 1370 | { 1371 | if ($oktaVerbose -eq $true) 1372 | { 1373 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1374 | } 1375 | throw $_ 1376 | } 1377 | return $request 1378 | } 1379 | 1380 | function oktaSuspendUserbyID() 1381 | { 1382 | param 1383 | ( 1384 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1385 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid 1386 | ) 1387 | 1388 | [string]$method = "Post" 1389 | [string]$resource = "/api/v1/users/" + $uid + "/lifecycle/suspend" 1390 | 1391 | try 1392 | { 1393 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 1394 | } 1395 | catch 1396 | { 1397 | if ($oktaVerbose -eq $true) 1398 | { 1399 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1400 | } 1401 | throw $_ 1402 | } 1403 | return $request 1404 | } 1405 | 1406 | function oktaUnSuspendUserbyID() 1407 | { 1408 | param 1409 | ( 1410 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1411 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid 1412 | ) 1413 | 1414 | [string]$method = "Post" 1415 | [string]$resource = "/api/v1/users/" + $uid + "/lifecycle/unsuspend" 1416 | 1417 | try 1418 | { 1419 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 1420 | } 1421 | catch 1422 | { 1423 | if ($oktaVerbose -eq $true) 1424 | { 1425 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1426 | } 1427 | throw $_ 1428 | } 1429 | return $request 1430 | } 1431 | 1432 | function oktaGetUsersbyAppID() 1433 | { 1434 | param 1435 | ( 1436 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1437 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 1438 | [parameter(Mandatory=$false)][switch]$skinny, 1439 | [parameter(Mandatory=$false)][int]$limit=$OktaOrgs[$oOrg].pageSize 1440 | ) 1441 | 1442 | [string]$method = "Get" 1443 | if ($skinny) 1444 | { 1445 | [string]$resource = "/api/v1/apps/" + $aid + "/skinny_users?limit=" + $limit 1446 | } else { 1447 | [string]$resource = "/api/v1/apps/" + $aid + "/users?limit=" + $limit 1448 | } 1449 | 1450 | try 1451 | { 1452 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 1453 | } 1454 | catch 1455 | { 1456 | if ($oktaVerbose -eq $true) 1457 | { 1458 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1459 | } 1460 | throw $_ 1461 | } 1462 | 1463 | <#foreach ($appUser in $request) 1464 | { 1465 | if ($skinny) 1466 | { 1467 | $appUser = OktaAppUserfromJson -appUser $appUser -skinny 1468 | } else { 1469 | $appUser = OktaAppUserfromJson -appUser $appUser 1470 | } 1471 | }#> 1472 | return $request 1473 | } 1474 | function oktaCreateCSRbyAppID() 1475 | { 1476 | param 1477 | ( 1478 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1479 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 1480 | [parameter(Mandatory=$false)][array]$dnsNames, 1481 | [parameter(Mandatory=$true)][string]$commonName, 1482 | [parameter(Mandatory=$false)][string]$countryName, 1483 | [parameter(Mandatory=$false)][string]$localityName, 1484 | [parameter(Mandatory=$false)][string]$organizationName, 1485 | [parameter(Mandatory=$false)][string]$organizationalUnitName, 1486 | [parameter(Mandatory=$false)][string]$stateOrProvinceName 1487 | ) 1488 | 1489 | [string]$method = "Post" 1490 | [string]$resource = "/api/v1/apps/" + $aid + "/credentials/csrs" 1491 | 1492 | $psobj = @{ 1493 | subject = @{ 1494 | commonName = $commonName 1495 | } 1496 | } 1497 | 1498 | [string[]]$subjectOptions = "countryName", "localityName", "organizationName", "organizationalUnitName", "stateOrProvinceName" 1499 | foreach ($option in $subjectOptions) 1500 | { 1501 | if (Get-Variable -Name $option -ErrorAction SilentlyContinue) 1502 | { 1503 | if ( (Get-Variable -Name $option -ValueOnly) -ne "" ) 1504 | { 1505 | $psobj.subject.add($option, (Get-Variable -Name $option -ValueOnly)) 1506 | } 1507 | } 1508 | } 1509 | 1510 | if ($dnsNames) 1511 | { 1512 | $temp = @{ dnsNames = $dnsNames} 1513 | $psobj.add("subjectAltNames", $temp) 1514 | } 1515 | 1516 | try 1517 | { 1518 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 1519 | } 1520 | catch 1521 | { 1522 | if ($oktaVerbose -eq $true) 1523 | { 1524 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1525 | } 1526 | throw $_ 1527 | } 1528 | 1529 | $offset=0 1530 | Write-Host "-----BEGIN CERTIFICATE REQUEST-----" 1531 | While ($offset -lt $request.csr.Length) 1532 | { 1533 | $len = ($request.csr.Length - $offset) 1534 | if ($len -ge 64) 1535 | { 1536 | $len = 64 1537 | } 1538 | Write-Host $request.csr.Substring($offset,$len) 1539 | $offset=$offset+$len 1540 | } 1541 | Write-Host "-----END CERTIFICATE REQUEST-----" 1542 | return $request 1543 | } 1544 | function oktaPublishCSRbyCSRandAppID() 1545 | { 1546 | param 1547 | ( 1548 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1549 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 1550 | [parameter(Mandatory=$true)][ValidateLength(43,43)][String]$csrid, 1551 | [parameter(Mandatory=$true)][string]$format="DER", 1552 | [parameter(Mandatory=$true)][string]$cert 1553 | ) 1554 | 1555 | $cert = $cert -replace "-----.+-----","" 1556 | $cert = $cert.Replace("`n","").Replace("`r","") 1557 | 1558 | [string]$method = "Post" 1559 | [string]$resource = "/api/v1/apps/" + $aid + "/credentials/csrs/" + $csrid + "/lifecycle/publish" 1560 | 1561 | #DER 1562 | $altHeaders = New-Object hashtable 1563 | $contentType = "application/json" 1564 | 1565 | if ("DER" -eq $format) 1566 | { 1567 | $contentType = "application/pkix-cert" 1568 | $altHeaders.Add('Content-Type', "application/pkix-cert") 1569 | $altHeaders.Add('Accept', "application/json") 1570 | $altHeaders.Add('Content-Transfer-Encoding', "base64") 1571 | } 1572 | #PEM point to file 1573 | #CER point to file 1574 | 1575 | try 1576 | { 1577 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -contentType $contentType -altHeaders $altHeaders -body $cert 1578 | } 1579 | catch 1580 | { 1581 | if ($oktaVerbose -eq $true) 1582 | { 1583 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1584 | } 1585 | throw $_ 1586 | } 1587 | 1588 | return $request 1589 | } 1590 | function oktaGetUsersbyAppIDWithStatus() 1591 | { 1592 | param 1593 | ( 1594 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1595 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 1596 | [ValidateSet('STAGED','SYNCING','OUT_OF_SYNC','ERROR')][string]$status, 1597 | [int]$limit=$OktaOrgs[$oOrg].pageSize 1598 | ) 1599 | 1600 | [string]$filter = "status eq " + '"'+$status+'"' 1601 | #$filter = [System.Web.HttpUtility]::UrlPathEncode($filter) 1602 | 1603 | [string]$method = "Get" 1604 | [string]$resource = "/api/v1/apps/" + $aid + "/users?filter=" + $filter + "&limit=" + $limit 1605 | try 1606 | { 1607 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 1608 | } 1609 | catch 1610 | { 1611 | if ($oktaVerbose -eq $true) 1612 | { 1613 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1614 | } 1615 | throw $_ 1616 | } 1617 | return $request 1618 | } 1619 | 1620 | function oktaListApps() 1621 | { 1622 | param 1623 | ( 1624 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1625 | [parameter(Mandatory=$false)][ValidateSet('ACTIVE','INACTIVE')][String]$status, 1626 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$uid, 1627 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$gid, 1628 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 1629 | [switch]$expand 1630 | ) 1631 | 1632 | #Make sure we don't build too many expressions 1633 | [int]$exp = 0 1634 | if ($uid) { $exp++} 1635 | if ($gid) { $exp++} 1636 | if ($status) { $exp++} 1637 | if ($exp -gt 1) 1638 | { 1639 | throw ("Can only use 1 expression to filter on user, group or active") 1640 | } 1641 | 1642 | [string]$method = "Get" 1643 | [string]$resource = '/api/v1/apps?limit=' + $limit 1644 | 1645 | $doFilter = $false 1646 | if ($status) 1647 | { 1648 | $doFilter = $true 1649 | [string]$filter = "status eq " + '"' + $status + '"' 1650 | } 1651 | if ($gid) 1652 | { 1653 | $doFilter = $true 1654 | [string]$filter = "group.id eq " + '"' + $gid + '"' 1655 | if ($expand) 1656 | { 1657 | $filter += "&expand=group/" + $gid 1658 | } 1659 | } 1660 | if ($uid) 1661 | { 1662 | $doFilter = $true 1663 | [string]$filter = "user.id eq " + '"' + $uid + '"' 1664 | if ($expand) 1665 | { 1666 | $filter += "&expand=user/" + $uid 1667 | } 1668 | } 1669 | if ($doFilter) 1670 | { 1671 | #$filter = [System.Web.HttpUtility]::UrlPathEncode($filter) 1672 | $resource = $resource + "&filter=" + $filter 1673 | } 1674 | 1675 | try 1676 | { 1677 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 1678 | } 1679 | catch 1680 | { 1681 | if ($oktaVerbose -eq $true) 1682 | { 1683 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1684 | } 1685 | throw $_ 1686 | } 1687 | foreach ($app in $request) 1688 | { 1689 | $app = OktaAppfromJson -app $app 1690 | } 1691 | return $request 1692 | 1693 | <# 1694 | $active = New-Object System.Collections.ArrayList 1695 | foreach ($app in $request) 1696 | { 1697 | if ($app.status -eq 'ACTIVE') 1698 | { 1699 | $_catch = $active.add($app) 1700 | } 1701 | } 1702 | return $active 1703 | #> 1704 | } 1705 | 1706 | function oktaGetActiveApps() 1707 | { 1708 | param 1709 | ( 1710 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1711 | [int]$limit=$OktaOrgs[$oOrg].pageSize 1712 | ) 1713 | 1714 | return oktaListApps -oOrg $oOrg -status ACTIVE -limit $limit 1715 | } 1716 | 1717 | function oktaGetAppGroups() 1718 | { 1719 | param 1720 | ( 1721 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1722 | [parameter(Mandatory=$true)][alias("AppId","applicationid")][ValidateLength(20,20)][String]$aid 1723 | ) 1724 | 1725 | [string]$method = "Get" 1726 | [string]$resource = '/api/v1/apps/' + $aid + '/groups' 1727 | 1728 | try 1729 | { 1730 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 1731 | } 1732 | catch 1733 | { 1734 | if ($oktaVerbose -eq $true) 1735 | { 1736 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1737 | } 1738 | throw $_ 1739 | } 1740 | 1741 | return $request 1742 | } 1743 | 1744 | function oktaListUsers() 1745 | { 1746 | param 1747 | ( 1748 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1749 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 1750 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination, 1751 | [parameter(Mandatory=$false)][String]$q, 1752 | [parameter(Mandatory=$false)][String]$search, 1753 | [parameter(Mandatory=$false)][String]$filter 1754 | ) 1755 | 1756 | [string]$resource = '/api/v1/users' + '?limit=' + $limit 1757 | [string]$method = "Get" 1758 | 1759 | if ($q) 1760 | { 1761 | [string]$resource = $resource + "&q=" + $q 1762 | } elseif ($search) 1763 | { 1764 | [string]$resource = $resource + "&search=" + $search 1765 | } 1766 | elseif ($filter) 1767 | { 1768 | [string]$resource = $resource + "&filter=" + $filter 1769 | } 1770 | 1771 | try 1772 | { 1773 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination $enablePagination 1774 | } 1775 | catch 1776 | { 1777 | if ($oktaVerbose -eq $true) 1778 | { 1779 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1780 | } 1781 | throw $_ 1782 | } 1783 | 1784 | foreach ($user in $request) 1785 | { 1786 | $user = OktaUserfromJson -user $user 1787 | } 1788 | return $request 1789 | } 1790 | 1791 | function oktaListAdministrators() 1792 | { 1793 | param 1794 | ( 1795 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1796 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 1797 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination, 1798 | [parameter(Mandatory=$false)][alias("userId")][ValidateLength(20,20)][String]$uid, 1799 | [switch]$groups 1800 | ) 1801 | 1802 | [string]$resource = '/api/internal/administrators' 1803 | [string]$method = "Get" 1804 | 1805 | if ($groups) 1806 | { 1807 | [string]$resource = $resource + "/groups" 1808 | } 1809 | elseif ($limit) 1810 | { 1811 | [string]$resource = $resource + "?limit=" + $limit 1812 | } elseif ($uid) 1813 | { 1814 | [string]$resource = $resource + "/" + $uid 1815 | } 1816 | 1817 | try 1818 | { 1819 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination $enablePagination 1820 | } 1821 | catch 1822 | { 1823 | if ($oktaVerbose -eq $true) 1824 | { 1825 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1826 | } 1827 | throw $_ 1828 | } 1829 | return $request 1830 | } 1831 | 1832 | function oktaListUsersbyStatus() 1833 | { 1834 | param 1835 | ( 1836 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1837 | [ValidateSet('STAGED','PROVISIONED','ACTIVE','RECOVERY','LOCKED_OUT','PASSWORD_EXPIRED','SUSPENDED','DEPROVISIONED')][string]$status, 1838 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 1839 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination 1840 | ) 1841 | 1842 | [string]$filter = "status eq " + '"'+$status+'"' 1843 | #$filter = [System.Web.HttpUtility]::UrlPathEncode($filter) 1844 | [string]$resource = "/api/v1/users?filter=" + $filter + "&limit=" + $limit 1845 | 1846 | [string]$method = "Get" 1847 | try 1848 | { 1849 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination $enablePagination 1850 | } 1851 | catch 1852 | { 1853 | if ($oktaVerbose -eq $true) 1854 | { 1855 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1856 | } 1857 | throw $_ 1858 | } 1859 | foreach ($user in $request) 1860 | { 1861 | $user = OktaUserfromJson -user $user 1862 | } 1863 | return $request 1864 | } 1865 | 1866 | function oktaListDeprovisionedUsers() 1867 | { 1868 | param 1869 | ( 1870 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1871 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 1872 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination 1873 | ) 1874 | 1875 | return oktaListUsersbyStatus -oOrg $oOrg -status "DEPROVISIONED" -limit $limit -enablePagination $enablePagination 1876 | } 1877 | 1878 | function oktaListActiveUsers() 1879 | { 1880 | param 1881 | ( 1882 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1883 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 1884 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination 1885 | ) 1886 | 1887 | return oktaListUsersbyStatus -oOrg $oOrg -status ACTIVE -limit $limit -enablePagination $enablePagination 1888 | } 1889 | 1890 | function oktaListUsersbyDate() 1891 | { 1892 | param 1893 | ( 1894 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1895 | [ValidateSet('STAGED','PROVISIONED','ACTIVE','RECOVERY','LOCKED_OUT','PASSWORD_EXPIRED','DEPROVISIONED')][string]$status, 1896 | #[ValidateSet('lastUpdated','lastLogin','statusChanged','activated','created','passwordChanged')][string]$field, 1897 | [parameter(Mandatory=$true)][ValidateSet('lastUpdated','activated')][string]$field, 1898 | [parameter(Mandatory=$true)][ValidateSet('gt','lt','eq','between')][string]$operator, 1899 | $date, 1900 | $start, 1901 | $stop, 1902 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 1903 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination 1904 | ) 1905 | 1906 | if ($operator -eq 'between') 1907 | { 1908 | try 1909 | { 1910 | if ($start -is [DateTime]) 1911 | { 1912 | $start = Get-Date $start.ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 1913 | } 1914 | if ($stop -is [DateTime]) 1915 | { 1916 | $stop = Get-Date $stop.ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 1917 | } 1918 | } 1919 | catch 1920 | { 1921 | Throw ("Bad or missing dates in filter") 1922 | } 1923 | [string]$filter = $field + " gt " + '"'+$start+'" and ' + $field + " lt " + '"'+$stop+'"' 1924 | } else { 1925 | try 1926 | { 1927 | if ($date -is [DateTime]) 1928 | { 1929 | $date = Get-Date $date.ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 1930 | } 1931 | } 1932 | catch 1933 | { 1934 | Throw ("Bad or missing dates in filter") 1935 | } 1936 | [string]$filter = $field + " " + $operator +" " + '"'+$date+'"' 1937 | } 1938 | 1939 | if ($status) 1940 | { 1941 | $filter = $filter + " and status eq " + '"'+$status+'"' 1942 | } 1943 | 1944 | #$filter = [System.Web.HttpUtility]::UrlPathEncode($filter) 1945 | [string]$resource = "/api/v1/users?filter=" + $filter + "&limit=" + $limit 1946 | [string]$method = "Get" 1947 | try 1948 | { 1949 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination $enablePagination 1950 | } 1951 | catch 1952 | { 1953 | if ($oktaVerbose -eq $true) 1954 | { 1955 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1956 | } 1957 | throw $_ 1958 | } 1959 | foreach ($user in $request) 1960 | { 1961 | $user = OktaUserfromJson -user $user 1962 | } 1963 | return $request 1964 | } 1965 | 1966 | function oktaListUsersbyAttribute() 1967 | { 1968 | param 1969 | ( 1970 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 1971 | [parameter(Mandatory=$true)][ValidateSet('login','email','firstName','lastName')][string]$field, 1972 | [parameter(Mandatory=$true)][ValidateSet('eq')][string]$operator, 1973 | [parameter(Mandatory=$true)][string]$value, 1974 | [ValidateSet('STAGED','PROVISIONED','ACTIVE','RECOVERY','LOCKED_OUT','PASSWORD_EXPIRED','DEPROVISIONED')][string]$status, 1975 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 1976 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination 1977 | ) 1978 | 1979 | [string]$filter = "profile." + $field + " " + $operator +" " + '"'+$value+'"' 1980 | 1981 | if ($status) 1982 | { 1983 | $filter = $filter + " and status eq " + '"'+$status+'"' 1984 | } 1985 | 1986 | #$filter = [System.Web.HttpUtility]::UrlPathEncode($filter) 1987 | [string]$resource = "/api/v1/users?filter=" + $filter + "&limit=" + $limit 1988 | [string]$method = "Get" 1989 | try 1990 | { 1991 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination $enablePagination 1992 | } 1993 | catch 1994 | { 1995 | if ($oktaVerbose -eq $true) 1996 | { 1997 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 1998 | } 1999 | throw $_ 2000 | } 2001 | foreach ($user in $request) 2002 | { 2003 | $user = OktaUserfromJson -user $user 2004 | } 2005 | return $request 2006 | } 2007 | 2008 | function oktaResetPasswordbyID() 2009 | { 2010 | param 2011 | ( 2012 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2013 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2014 | [boolean]$sendEmail = $False 2015 | ) 2016 | 2017 | [string]$method = "Post" 2018 | [string]$resource = '/api/v1/users/' + $uid + '/lifecycle/reset_password?sendEmail=' + $sendEmail 2019 | 2020 | try 2021 | { 2022 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2023 | } 2024 | catch 2025 | { 2026 | if ($oktaVerbose -eq $true) 2027 | { 2028 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2029 | } 2030 | throw $_ 2031 | } 2032 | foreach ($user in $request) 2033 | { 2034 | $user = OktaUserfromJson -user $user 2035 | } 2036 | return $request 2037 | } 2038 | 2039 | function oktaConvertUsertoFederation() 2040 | { 2041 | param 2042 | ( 2043 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2044 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2045 | [parameter(Mandatory=$false)][ValidateSet('FEDERATION','OKTA')][String]$source='FEDERATION' 2046 | ) 2047 | 2048 | [string]$method = "Post" 2049 | [string]$resource = '/api/v1/users/' + $uid + '/lifecycle/reset_password?provider=' + $source + '&sendEmail=false' 2050 | 2051 | try 2052 | { 2053 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2054 | } 2055 | catch 2056 | { 2057 | if ($oktaVerbose -eq $true) 2058 | { 2059 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2060 | } 2061 | throw $_ 2062 | } 2063 | #foreach ($user in $request) 2064 | #{ 2065 | # $user = OktaUserfromJson -user $user 2066 | #} 2067 | return $request 2068 | } 2069 | 2070 | function oktaDeactivateUserbyID() 2071 | { 2072 | param 2073 | ( 2074 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2075 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid 2076 | ) 2077 | 2078 | [string]$resource = '/api/v1/users/' + $uid + '/lifecycle/deactivate' 2079 | [string]$method = "Post" 2080 | 2081 | try 2082 | { 2083 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2084 | } 2085 | catch 2086 | { 2087 | if ($oktaVerbose -eq $true) 2088 | { 2089 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2090 | } 2091 | throw $_ 2092 | } 2093 | 2094 | return $request 2095 | } 2096 | 2097 | function oktaActivateUserbyId() 2098 | { 2099 | param 2100 | ( 2101 | [parameter(Mandatory=$false)] 2102 | [ValidateLength(1,100)] 2103 | [String]$oOrg=$oktaDefOrg, 2104 | [Parameter(Mandatory=$false)] 2105 | [ValidateLength(20,20)][ 2106 | string]$uid, 2107 | [parameter(Mandatory=$false)] 2108 | [string]$username 2109 | ) 2110 | if (!$uid) 2111 | { 2112 | if ($username) 2113 | { 2114 | $uid = (oktaGetUserbyID -oOrg $oOrg -userName $username).id 2115 | } else { 2116 | throw ("Must send one of uid or username") 2117 | } 2118 | } 2119 | 2120 | [string]$resource = '/api/v1/users/' + $uid + '/lifecycle/activate?sendEmail=False' 2121 | [string]$method = "Post" 2122 | try 2123 | { 2124 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2125 | } 2126 | catch 2127 | { 2128 | if ($oktaVerbose -eq $true) 2129 | { 2130 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2131 | } 2132 | throw $_ 2133 | } 2134 | 2135 | return $request 2136 | } 2137 | 2138 | function oktaUpdateApp() 2139 | { 2140 | param 2141 | ( 2142 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2143 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 2144 | [parameter(Mandatory=$true)][object]$app 2145 | ) 2146 | 2147 | $psobj = $app 2148 | 2149 | [string]$resource = "/api/v1/apps/" + $aid 2150 | [string]$method = "Put" 2151 | 2152 | try 2153 | { 2154 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 2155 | } 2156 | catch 2157 | { 2158 | if ($oktaVerbose -eq $true) 2159 | { 2160 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2161 | } 2162 | throw $_ 2163 | } 2164 | return $request 2165 | } 2166 | 2167 | function oktaUpdateAppOverrides() 2168 | { 2169 | param 2170 | ( 2171 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2172 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 2173 | [parameter(Mandatory=$false)][String]$ssoAcsUrlOverride, 2174 | [parameter(Mandatory=$false)][String]$audienceOverride, 2175 | [parameter(Mandatory=$false)][String]$recipientOverride, 2176 | [parameter(Mandatory=$false)][String]$destinationOverride 2177 | ) 2178 | 2179 | $app = oktaGetAppbyId -oOrg $oOrg -aid $aid 2180 | 2181 | [string[]]$overrides = "ssoAcsUrlOverride","audienceOverride","recipientOverride","destinationOverride" 2182 | 2183 | foreach ($override in $overrides) 2184 | { 2185 | if (Get-Variable -Name $override -ErrorAction SilentlyContinue) 2186 | { 2187 | $app.settings.signOn.$override = (Get-Variable -Name $override -ValueOnly) 2188 | } 2189 | } 2190 | 2191 | $new = @{signOnMode=$app.signOnMode; label=$app.label; name=$app.name; settings=$app.settings} 2192 | 2193 | oktaUpdateApp -oOrg $org -aid $aid -app $new 2194 | } 2195 | 2196 | function oktaGetAppbyId() 2197 | { 2198 | param 2199 | ( 2200 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2201 | [parameter(Mandatory=$true)][ValidateLength(1,100)][String]$aid 2202 | ) 2203 | 2204 | [string]$resource = "/api/v1/apps/" + $aid 2205 | [string]$method = "Get" 2206 | try 2207 | { 2208 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2209 | } 2210 | catch 2211 | { 2212 | if ($oktaVerbose -eq $true) 2213 | { 2214 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2215 | } 2216 | throw $_ 2217 | } 2218 | return $request 2219 | } 2220 | 2221 | function oktaGetAppsbyUserId() 2222 | { 2223 | param 2224 | ( 2225 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2226 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2227 | [switch]$expand 2228 | ) 2229 | 2230 | if ($expand) 2231 | { 2232 | $apps = oktaListApps -oOrg $oOrg -uid $uid -expand 2233 | } else { 2234 | $apps = oktaListApps -oOrg $oOrg -uid $uid 2235 | } 2236 | 2237 | return $apps 2238 | } 2239 | 2240 | function oktaGetAppLinksbyUserId() 2241 | { 2242 | param 2243 | ( 2244 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2245 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid 2246 | ) 2247 | [string]$resource = "/api/v1/users/" + $uid + "/appLinks" 2248 | [string]$method = "Get" 2249 | 2250 | try 2251 | { 2252 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2253 | } 2254 | catch 2255 | { 2256 | if ($oktaVerbose -eq $true) 2257 | { 2258 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2259 | } 2260 | throw $_ 2261 | } 2262 | return $request 2263 | } 2264 | 2265 | function oktaDeleteGroupbyId() 2266 | { 2267 | param 2268 | ( 2269 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2270 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$gid 2271 | ) 2272 | 2273 | [string]$resource = '/api/v1/groups/' + $gid 2274 | [string]$method = "Delete" 2275 | try 2276 | { 2277 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2278 | } 2279 | catch 2280 | { 2281 | if ($oktaVerbose -eq $true) 2282 | { 2283 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2284 | } 2285 | throw $_ 2286 | } 2287 | return $request 2288 | } 2289 | 2290 | function oktaToggleAppAssignfromGroup() 2291 | { 2292 | param 2293 | ( 2294 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2295 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$gid, 2296 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 2297 | [parameter(Mandatory=$true)][ValidateSet("Add","Remove")][String]$action 2298 | ) 2299 | 2300 | [string]$resource = '/api/v1/apps/' + $aid + '/groups/' + $gid 2301 | 2302 | if ("Add" -eq $action) 2303 | { 2304 | [string]$method = "Put" 2305 | } else { 2306 | [string]$method = "Delete" 2307 | } 2308 | 2309 | try 2310 | { 2311 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2312 | } 2313 | catch 2314 | { 2315 | if ($oktaVerbose -eq $true) 2316 | { 2317 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2318 | } 2319 | throw $_ 2320 | } 2321 | return $request 2322 | } 2323 | 2324 | function oktaCreateGroup() 2325 | { 2326 | param 2327 | ( 2328 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2329 | [parameter(Mandatory=$true)][ValidateLength(1,255)][String]$name, 2330 | [parameter(Mandatory=$false)][ValidateLength(1,1024)][String]$description=$null 2331 | ) 2332 | 2333 | $psobj = @{ 2334 | profile = @{ 2335 | name = $name 2336 | description = $description 2337 | } 2338 | } 2339 | 2340 | [string]$resource = '/api/v1/groups' 2341 | 2342 | [string]$method = "Post" 2343 | 2344 | try 2345 | { 2346 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 2347 | } 2348 | catch 2349 | { 2350 | if ($oktaVerbose -eq $true) 2351 | { 2352 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2353 | } 2354 | throw $_ 2355 | } 2356 | return $request 2357 | } 2358 | 2359 | function oktaGetGroupbyId() 2360 | { 2361 | param 2362 | ( 2363 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2364 | [parameter(Mandatory=$true)][alias("groupId")][ValidateLength(20,20)][String]$gid, 2365 | [parameter(Mandatory=$false)][switch]$expand 2366 | ) 2367 | 2368 | [string]$resource = '/api/v1/groups/' + $gid 2369 | if ($expand) 2370 | { 2371 | $resource += '?expand=app,stats,apps' 2372 | } 2373 | [string]$method = "Get" 2374 | 2375 | try 2376 | { 2377 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2378 | } 2379 | catch 2380 | { 2381 | if ($oktaVerbose -eq $true) 2382 | { 2383 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2384 | } 2385 | throw $_ 2386 | } 2387 | return $request 2388 | } 2389 | 2390 | function oktaGetGroupStatsbyId() 2391 | { 2392 | param 2393 | ( 2394 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2395 | [parameter(Mandatory=$true)][alias("groupId")][ValidateLength(20,20)][String]$gid 2396 | ) 2397 | 2398 | #[string]$resource = '/api/v1/groups/' + $gid + '/stats' 2399 | [string]$resource = '/api/v1/groups/' + $gid + '?expand=stats,app,user,groupPushMapping' 2400 | [string]$method = "Get" 2401 | 2402 | try 2403 | { 2404 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2405 | } 2406 | catch 2407 | { 2408 | if ($oktaVerbose -eq $true) 2409 | { 2410 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2411 | } 2412 | throw $_ 2413 | } 2414 | return $request 2415 | } 2416 | 2417 | function oktaGetGroupsbyUserId() 2418 | { 2419 | param 2420 | ( 2421 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid, 2422 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg 2423 | ) 2424 | 2425 | [string]$resource = "/api/v1/users/" + $uid + "/groups" 2426 | [string]$method = "Get" 2427 | try 2428 | { 2429 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2430 | } 2431 | catch 2432 | { 2433 | if ($oktaVerbose -eq $true) 2434 | { 2435 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2436 | } 2437 | throw $_ 2438 | } 2439 | return $request 2440 | } 2441 | 2442 | function oktaDelUserFromAllGroups() 2443 | { 2444 | param 2445 | ( 2446 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2447 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid 2448 | ) 2449 | 2450 | $groups = oktaGetGroupsbyUserId -oOrg $oOrg -uid $uid 2451 | foreach ($og in $groups) 2452 | { 2453 | if ($og.type -eq 'OKTA_GROUP') 2454 | { 2455 | oktaDelUseridfromGroupid -oOrg $oOrg -uid $uid -gid $og.id 2456 | } 2457 | } 2458 | } 2459 | 2460 | function oktaGetGroupsbyquery() 2461 | { 2462 | param 2463 | ( 2464 | [parameter(Mandatory=$true)][String]$query, 2465 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg 2466 | ) 2467 | oktaListGroups -oOrg $oOrg -query $query 2468 | } 2469 | 2470 | function oktaGetGroupsAll() 2471 | { 2472 | param 2473 | ( 2474 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg 2475 | ) 2476 | 2477 | oktaListGroups -oOrg $oOrg 2478 | } 2479 | 2480 | function oktaListGroups() 2481 | { 2482 | param 2483 | ( 2484 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2485 | [parameter(Mandatory=$false)][String]$query, 2486 | [parameter(Mandatory=$false)][String]$filter, 2487 | [parameter(Mandatory=$false)][int]$limit=$OktaOrgs[$oOrg].pageSize, 2488 | [parameter(Mandatory=$false)][switch]$expand 2489 | ) 2490 | 2491 | [string]$resource = "/api/v1/groups?limit=" + $limit 2492 | if ($query) 2493 | { 2494 | $resource += "&q=" + $query 2495 | } 2496 | if ($filter) 2497 | { 2498 | $resource += "&filter=" + $filter 2499 | } 2500 | 2501 | if ($expand) 2502 | { 2503 | $resource += "&expand=app,stats" 2504 | } 2505 | 2506 | [string]$method = "Get" 2507 | 2508 | try 2509 | { 2510 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -limit $limit 2511 | } 2512 | catch 2513 | { 2514 | if ($oktaVerbose -eq $true) 2515 | { 2516 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2517 | } 2518 | throw $_ 2519 | } 2520 | return $request 2521 | } 2522 | 2523 | function oktaGetRolesByGroupId() 2524 | { 2525 | param 2526 | ( 2527 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2528 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$gid 2529 | ) 2530 | 2531 | [string]$resource = "/api/v1/groups/" + $gid + "/roles" 2532 | [string]$method = "Get" 2533 | 2534 | try 2535 | { 2536 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination:$true 2537 | } 2538 | catch 2539 | { 2540 | if ($oktaVerbose -eq $true) 2541 | { 2542 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2543 | } 2544 | throw $_ 2545 | } 2546 | return $request 2547 | } 2548 | 2549 | function oktaGetRolesByUserId() 2550 | { 2551 | param 2552 | ( 2553 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2554 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid 2555 | ) 2556 | 2557 | [string]$resource = "/api/v1/users/" + $uid + "/roles" 2558 | [string]$method = "Get" 2559 | 2560 | try 2561 | { 2562 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination:$true 2563 | } 2564 | catch 2565 | { 2566 | if ($oktaVerbose -eq $true) 2567 | { 2568 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2569 | } 2570 | throw $_ 2571 | } 2572 | return $request 2573 | } 2574 | 2575 | function oktaAddUsertoRoles() 2576 | { 2577 | param 2578 | ( 2579 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2580 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2581 | [Parameter(Mandatory=$true)][ValidateSet("SUPER_ADMIN","ORG_ADMIN","API_ACCESS_MANAGEMENT_ADMIN","APP_ADMIN","USER_ADMIN","MOBILE_ADMIN","READ_ONLY_ADMIN", "HELP_DESK_ADMIN")][String]$roleType 2582 | ) 2583 | 2584 | [string]$resource = "/api/v1/users/" + $uid + "/roles" 2585 | [string]$method = "Post" 2586 | $psobj = @{ "type" = $roleType } 2587 | 2588 | try 2589 | { 2590 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 2591 | } 2592 | catch 2593 | { 2594 | if ($oktaVerbose -eq $true) 2595 | { 2596 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2597 | } 2598 | throw $_ 2599 | } 2600 | return $request 2601 | } 2602 | 2603 | function oktaDelUserFromRoles() 2604 | { 2605 | param 2606 | ( 2607 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2608 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2609 | [parameter(Mandatory=$true)][ValidateLength(14,24)][String]$rid 2610 | ) 2611 | 2612 | [string]$resource = "/api/v1/users/" + $uid + "/roles/" + $rid 2613 | [string]$method = "Delete" 2614 | 2615 | try 2616 | { 2617 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2618 | } 2619 | catch 2620 | { 2621 | if ($oktaVerbose -eq $true) 2622 | { 2623 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2624 | } 2625 | throw $_ 2626 | } 2627 | return $request 2628 | } 2629 | 2630 | function oktaGetRoleTargetsByUserId() 2631 | { 2632 | param 2633 | ( 2634 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2635 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid, 2636 | [parameter(Mandatory=$true)][alias("roleId")][ValidateLength(14,24)][String]$rid 2637 | ) 2638 | 2639 | [string]$resource = "/api/v1/users/" + $uid + "/roles/" + $rid + "/targets/groups" 2640 | [string]$method = "Get" 2641 | 2642 | try 2643 | { 2644 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination:$true 2645 | } 2646 | catch 2647 | { 2648 | if ($oktaVerbose -eq $true) 2649 | { 2650 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2651 | } 2652 | throw $_ 2653 | } 2654 | return $request 2655 | } 2656 | 2657 | function oktaAddRoleTargetsByUserId() 2658 | { 2659 | param 2660 | ( 2661 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2662 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid, 2663 | [parameter(Mandatory=$true)][alias("roleId")][ValidateLength(14,24)][String]$rid, 2664 | [parameter(Mandatory=$true)][alias("groupId")][ValidateLength(20,20)][String]$gid 2665 | ) 2666 | 2667 | [string]$resource = "/api/v1/users/" + $uid + "/roles/" + $rid + "/targets/groups/" + $gid 2668 | [string]$method = "Put" 2669 | 2670 | try 2671 | { 2672 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination:$true 2673 | } 2674 | catch 2675 | { 2676 | if ($oktaVerbose -eq $true) 2677 | { 2678 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2679 | } 2680 | throw $_ 2681 | } 2682 | return $request 2683 | } 2684 | 2685 | function oktaDelRoleTargetsByUserId() 2686 | { 2687 | param 2688 | ( 2689 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2690 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid, 2691 | [parameter(Mandatory=$true)][alias("roleId")][ValidateLength(14,24)][String]$rid, 2692 | [parameter(Mandatory=$true)][alias("groupId")][ValidateLength(20,20)][String]$gid 2693 | ) 2694 | 2695 | [string]$resource = "/api/v1/users/" + $uid + "/roles/" + $rid + "/targets/groups/" + $gid 2696 | [string]$method = "Delete" 2697 | 2698 | try 2699 | { 2700 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination:$true 2701 | } 2702 | catch 2703 | { 2704 | if ($oktaVerbose -eq $true) 2705 | { 2706 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2707 | } 2708 | throw $_ 2709 | } 2710 | return $request 2711 | } 2712 | 2713 | function oktaAddUseridtoGroupid() 2714 | { 2715 | param 2716 | ( 2717 | [parameter(Mandatory=$false)] 2718 | [alias("userId")] 2719 | [ValidateLength(20,20)] 2720 | [String]$uid, 2721 | [parameter(Mandatory=$true)] 2722 | [ValidateLength(20,20)] 2723 | [String]$gid, 2724 | [parameter(Mandatory=$false)] 2725 | [ValidateLength(1,100)] 2726 | [String]$oOrg=$oktaDefOrg, 2727 | [parameter(Mandatory=$false)] 2728 | [string]$username 2729 | ) 2730 | 2731 | if (!$uid) 2732 | { 2733 | if ($username) 2734 | { 2735 | $uid = (oktaGetUserbyID -oOrg $oOrg -userName $username).id 2736 | } else { 2737 | throw ("Must send one of uid or username") 2738 | } 2739 | } 2740 | 2741 | [string]$resource = "/api/v1/groups/" + $gid + "/users/" + $uid 2742 | [string]$method = "Put" 2743 | try 2744 | { 2745 | $request = _oktaNewCall -resource $resource -method $method -oOrg $oOrg 2746 | } 2747 | catch 2748 | { 2749 | if ($oktaVerbose -eq $true) 2750 | { 2751 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2752 | } 2753 | throw $_ 2754 | } 2755 | return $request 2756 | } 2757 | 2758 | function oktaDelUseridfromGroupid() 2759 | { 2760 | param 2761 | ( 2762 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2763 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid, 2764 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$gid 2765 | ) 2766 | 2767 | [string]$resource = "/api/v1/groups/" + $gid + "/users/" + $uid 2768 | [string]$method = "Delete" 2769 | 2770 | try 2771 | { 2772 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2773 | } 2774 | catch 2775 | { 2776 | if ($oktaVerbose -eq $true) 2777 | { 2778 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2779 | } 2780 | throw $_ 2781 | } 2782 | return $request 2783 | } 2784 | 2785 | function oktaDelUseridfromAppid() 2786 | { 2787 | param 2788 | ( 2789 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2790 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid, 2791 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid 2792 | ) 2793 | 2794 | [string]$resource = "/api/v1/apps/" + $aid + "/users/" + $uid 2795 | [string]$method = "Delete" 2796 | 2797 | try 2798 | { 2799 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2800 | } 2801 | catch 2802 | { 2803 | if ($oktaVerbose -eq $true) 2804 | { 2805 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2806 | } 2807 | throw $_ 2808 | } 2809 | return $request 2810 | } 2811 | 2812 | function oktaGetprofilebyId() 2813 | { 2814 | param 2815 | ( 2816 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2817 | [parameter(Mandatory=$true)][alias("userId")][ValidateLength(20,20)][String]$uid 2818 | ) 2819 | $profile = (oktaGetUserbyID -oOrg $oOrg -uid $uid).profile 2820 | return $profile 2821 | } 2822 | 2823 | function oktaGetAppProfilebyUserId() 2824 | { 2825 | param 2826 | ( 2827 | [parameter(Mandatory=$true)][alias("appid")][ValidateLength(20,20)][String]$aid, 2828 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2829 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg 2830 | ) 2831 | 2832 | [string]$resource = "/api/v1/apps/" + $aid + "/users/" + $uid 2833 | [string]$method = "Get" 2834 | 2835 | try 2836 | { 2837 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2838 | } 2839 | catch 2840 | { 2841 | if ($oktaVerbose -eq $true) 2842 | { 2843 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2844 | } 2845 | throw $_ 2846 | } 2847 | return $request 2848 | } 2849 | 2850 | function oktaGetMasterProfile() 2851 | { 2852 | param 2853 | ( 2854 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2855 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg 2856 | ) 2857 | <# 2858 | currently requires profile master to be defined in Okta_org.ps1 2859 | Need to enhance to 'discover' the profile master. Nothing eloquent 2860 | comes to mind at time of writing. 2861 | #> 2862 | $aid = $oktaOrgs[$oOrg].ProfileMaster 2863 | oktaGetAppProfilebyUserId -aid $aid -uid $uid -oOrg $oOrg 2864 | } 2865 | 2866 | function oktaGetGroupMembersbyId() 2867 | { 2868 | param 2869 | ( 2870 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2871 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$gid, 2872 | [parameter(Mandatory=$false)][switch]$skinny, 2873 | [int]$limit=$OktaOrgs[$oOrg].pageSize, 2874 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination 2875 | ) 2876 | if ($skinny) 2877 | { 2878 | [string]$resource = "/api/v1/groups/" + $gid + "/skinny_users?limit=" + $limit 2879 | } else { 2880 | [string]$resource = "/api/v1/groups/" + $gid + "/users?limit=" + $limit 2881 | } 2882 | 2883 | [string]$method = "Get" 2884 | 2885 | try 2886 | { 2887 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination:$true 2888 | } 2889 | catch 2890 | { 2891 | if ($oktaVerbose -eq $true) 2892 | { 2893 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2894 | } 2895 | throw $_ 2896 | } 2897 | return $request 2898 | } 2899 | 2900 | function oktaDeleteUserfromGroup() 2901 | { 2902 | param 2903 | ( 2904 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2905 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2906 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$gid 2907 | ) 2908 | 2909 | [string]$resource = "/api/v1/groups/" + $gid + "/users/" + $uid 2910 | [string]$method = "Delete" 2911 | 2912 | try 2913 | { 2914 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2915 | } 2916 | catch 2917 | { 2918 | if ($oktaVerbose -eq $true) 2919 | { 2920 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2921 | } 2922 | throw $_ 2923 | } 2924 | return $request 2925 | } 2926 | 2927 | function oktaSetAppCredentials() 2928 | { 2929 | param 2930 | ( 2931 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2932 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 2933 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 2934 | [parameter(Mandatory=$false)][string]$newuserName, 2935 | [parameter(Mandatory=$false)][string]$newPassword 2936 | ) 2937 | 2938 | #$_cur = oktaGetAppProfilebyUserId -aid $aid -uid $uid -oOrg $oOrg 2939 | $credentials = New-Object System.Collections.Hashtable 2940 | if ($newPassword) 2941 | { 2942 | $_c = $credentials.Add('password',$newPassword) 2943 | } 2944 | if ($newuserName) { 2945 | $_c = $credentials.Add('userName',$newuserName) 2946 | } 2947 | 2948 | $psobj = @{ 2949 | 'credentials' = $credentials 2950 | } 2951 | [string]$resource = "/api/v1/apps/" + $aid + "/users/" + $uid 2952 | [string]$method = "Post" 2953 | 2954 | try 2955 | { 2956 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 2957 | } 2958 | catch 2959 | { 2960 | if ($oktaVerbose -eq $true) 2961 | { 2962 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2963 | } 2964 | throw $_ 2965 | } 2966 | return $request 2967 | } 2968 | 2969 | function oktaUnlockUserbyId() 2970 | { 2971 | param 2972 | ( 2973 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2974 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid 2975 | ) 2976 | [string]$resource = '/api/v1/users/' + $uid + '/lifecycle/unlock' 2977 | [string]$method = "Post" 2978 | try 2979 | { 2980 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 2981 | #$request = _oktaOldCall -method $method -resource $resource -oOrg $oOrg 2982 | } 2983 | catch 2984 | { 2985 | if ($oktaVerbose -eq $true) 2986 | { 2987 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 2988 | } 2989 | throw $_ 2990 | } 2991 | return $request 2992 | } 2993 | 2994 | function oktaConvertGroupbyId() 2995 | { 2996 | param 2997 | ( 2998 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 2999 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$gid 3000 | ) 3001 | [string]$resource = '/api/internal/groups/' + $gid + '/convert' 3002 | [string]$method = "Post" 3003 | try 3004 | { 3005 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3006 | } 3007 | catch 3008 | { 3009 | if ($oktaVerbose -eq $true) 3010 | { 3011 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3012 | } 3013 | throw $_ 3014 | } 3015 | return $request 3016 | } 3017 | 3018 | function oktaUpdateUserProfilebyID() 3019 | { 3020 | param 3021 | ( 3022 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3023 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 3024 | [parameter(Mandatory=$true)][alias("newProfile","updatedProfile")][object]$Profile, 3025 | [switch]$partial 3026 | ) 3027 | 3028 | $psobj = @{ profile = $Profile } 3029 | 3030 | if ($partial) 3031 | { 3032 | [string]$method = "Post" 3033 | } else { 3034 | [string]$method = "Put" 3035 | } 3036 | [string]$resource = "/api/v1/users/" + $uid 3037 | try 3038 | { 3039 | $request = _oktaNewCall -oOrg $oOrg -method $method -resource $resource -body $psobj 3040 | } 3041 | catch 3042 | { 3043 | if ($oktaVerbose -eq $true) 3044 | { 3045 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3046 | } 3047 | throw $_ 3048 | } 3049 | return $request 3050 | } 3051 | 3052 | function oktaUpdateAppProfilebyUserId() 3053 | { 3054 | param 3055 | ( 3056 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3057 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 3058 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 3059 | [parameter(Mandatory=$true)][alias("newProfile","updatedProfile")][object]$profile, 3060 | [switch]$partial 3061 | ) 3062 | 3063 | $psobj = @{ profile = $profile } 3064 | 3065 | [string]$resource = "/api/v1/apps/" + $aid + "/users/" + $uid 3066 | 3067 | if ($partial) 3068 | { 3069 | [string]$method = "Post" 3070 | } else { 3071 | [string]$method = "Put" 3072 | } 3073 | 3074 | try 3075 | { 3076 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 3077 | } 3078 | catch 3079 | { 3080 | if ($oktaVerbose -eq $true) 3081 | { 3082 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3083 | } 3084 | throw $_ 3085 | } 3086 | return $request 3087 | } 3088 | 3089 | function oktaUpdateAppExternalIdbyUserId() 3090 | { 3091 | param 3092 | ( 3093 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3094 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid, 3095 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 3096 | [parameter(Mandatory=$true)][string]$externalId 3097 | ) 3098 | 3099 | 3100 | $psobj = @{ externalId = $externalId } 3101 | 3102 | [string]$resource = "/api/v1/apps/" + $aid + "/users/" + $uid 3103 | [string]$method = "Post" 3104 | 3105 | try 3106 | { 3107 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 3108 | } 3109 | catch 3110 | { 3111 | if ($oktaVerbose -eq $true) 3112 | { 3113 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3114 | } 3115 | throw $_ 3116 | } 3117 | return $request 3118 | } 3119 | 3120 | function oktaActivateFactorByUser() 3121 | { 3122 | param 3123 | ( 3124 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3125 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$uid, 3126 | [parameter(Mandatory=$false)][ValidateLength(1,255)][String]$username, 3127 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$fid, 3128 | [parameter(Mandatory=$true)][ValidateLength(6,6)][String]$passCode 3129 | 3130 | ) 3131 | 3132 | if (!$uid) 3133 | { 3134 | if ($username) 3135 | { 3136 | $uid = (oktaGetUserbyID -oOrg $oOrg -userName $username).id 3137 | } else { 3138 | throw ("Must send one of uid or username") 3139 | } 3140 | } 3141 | 3142 | $body = @{ passCode = $passCode } 3143 | 3144 | [string]$resource = '/api/v1/users/' + $uid + '/factors/' + $fid + '/lifecycle/activate' 3145 | [string]$method = "Post" 3146 | 3147 | try 3148 | { 3149 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $body 3150 | } 3151 | catch 3152 | { 3153 | if ($oktaVerbose -eq $true) 3154 | { 3155 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3156 | } 3157 | throw $_ 3158 | } 3159 | return $request 3160 | } 3161 | 3162 | function oktaEnrollFactorByUser() 3163 | { 3164 | param 3165 | ( 3166 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3167 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$uid, 3168 | [parameter(Mandatory=$false)][ValidateLength(1,255)][String]$username, 3169 | [parameter(Mandatory=$true)][ValidateSet('push','sms','call','token','token:software:totp','token:hardware','question','web','email')][String]$factorType, 3170 | [parameter(Mandatory=$true)][ValidateSet('OKTA','RSA','SYMANTEC','GOOGLE','DUO','YUBICO','DEL_OATH')][String]$provider, 3171 | [parameter(Mandatory=$true)]$factorProfile, 3172 | [parameter(Mandatory=$false)]$verifyData, 3173 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$fid, 3174 | [parameter(Mandatory=$false)][switch]$update, 3175 | [parameter(Mandatory=$false)][switch]$updatePhone, 3176 | [parameter(Mandatory=$false)][switch]$activate 3177 | ) 3178 | 3179 | if (!$uid) 3180 | { 3181 | if ($username) 3182 | { 3183 | $uid = (oktaGetUserbyID -oOrg $oOrg -userName $username).id 3184 | } else { 3185 | throw ("Must send one of uid or username") 3186 | } 3187 | } 3188 | 3189 | [string]$method = "Post" 3190 | [string]$resource = '/api/v1/users/' + $uid + '/factors' 3191 | $params = New-Object System.Collections.Hashtable 3192 | 3193 | $body = @{ 3194 | factorType = $factorType 3195 | provider = $provider 3196 | profile = $factorProfile 3197 | } 3198 | if ($verifyData) 3199 | { 3200 | $body.Add("verify", $verifyData) 3201 | } 3202 | 3203 | if ($update) 3204 | { 3205 | #$resource = $resource + '/' + $fid 3206 | $body = @{ profile = $factorProfile } 3207 | } elseif ($activate) 3208 | { 3209 | $params.Add("activate",$true) 3210 | } 3211 | if ($updatePhone){$params.Add("updatePhone",$true)} 3212 | 3213 | $resource = oktaBuildURI -resource $resource -params $params 3214 | try 3215 | { 3216 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $body 3217 | } 3218 | catch 3219 | { 3220 | if ($oktaVerbose -eq $true) 3221 | { 3222 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3223 | } 3224 | throw $_ 3225 | } 3226 | return $request 3227 | } 3228 | 3229 | function oktaActivateFactorByUser() 3230 | { 3231 | param 3232 | ( 3233 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3234 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 3235 | [parameter(Mandatory=$true)][ValidateLength(1,255)][String]$fid, 3236 | [parameter(Mandatory=$false)][ValidateLength(5,20)][String]$passCode 3237 | ) 3238 | 3239 | if ($passCode) 3240 | { 3241 | $body = @{ passCode = $passCode } 3242 | } else { 3243 | $body = $null 3244 | } 3245 | [string]$resource = '/api/v1/users/' + $uid + '/factors/' + $fid + '/lifecycle/activate' 3246 | [string]$method = "Post" 3247 | 3248 | try 3249 | { 3250 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $body 3251 | } 3252 | catch 3253 | { 3254 | if ($oktaVerbose -eq $true) 3255 | { 3256 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3257 | } 3258 | throw $_ 3259 | } 3260 | return $request 3261 | } 3262 | 3263 | function oktaGetFactorsbyUser() 3264 | { 3265 | param 3266 | ( 3267 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3268 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$uid, 3269 | [parameter(Mandatory=$false)][ValidateLength(1,255)][String]$username, 3270 | [parameter(Mandatory=$false)][switch]$eligible 3271 | ) 3272 | if (!$uid) 3273 | { 3274 | if ($username) 3275 | { 3276 | $uid = (oktaGetUserbyID -oOrg $oOrg -userName $username).id 3277 | } else { 3278 | throw ("Must send one of uid or username") 3279 | } 3280 | } 3281 | 3282 | [string]$resource = '/api/v1/users/' + $uid + '/factors' 3283 | if ($eligible) 3284 | { 3285 | $resource = $resource + '/catalog' 3286 | } 3287 | [string]$method = "Get" 3288 | try 3289 | { 3290 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3291 | } 3292 | catch 3293 | { 3294 | if ($oktaVerbose -eq $true) 3295 | { 3296 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3297 | } 3298 | throw $_ 3299 | } 3300 | return $request 3301 | } 3302 | 3303 | function oktaGetFactorbyUser() 3304 | { 3305 | param 3306 | ( 3307 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3308 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 3309 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$fid 3310 | ) 3311 | 3312 | [string]$method = "Get" 3313 | [string]$resource = '/api/v1/users/' + $uid + '/factors/' + $fid 3314 | 3315 | try 3316 | { 3317 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3318 | } 3319 | catch 3320 | { 3321 | if ($oktaVerbose -eq $true) 3322 | { 3323 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3324 | } 3325 | throw $_ 3326 | } 3327 | return $request 3328 | } 3329 | 3330 | function oktaResetFactorbyUser() 3331 | { 3332 | param 3333 | ( 3334 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3335 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$uid, 3336 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$fid, 3337 | [parameter(Mandatory=$false)][ValidateLength(1,255)][String]$username 3338 | ) 3339 | 3340 | if (!$uid) 3341 | { 3342 | if ($username) 3343 | { 3344 | $uid = (oktaGetUserbyID -oOrg $oOrg -userName $username).id 3345 | } else { 3346 | throw ("Must send one of uid or username") 3347 | } 3348 | } 3349 | 3350 | [string]$method = "Delete" 3351 | [string]$resource = '/api/v1/users/' + $uid + '/factors/' + $fid 3352 | 3353 | try 3354 | { 3355 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3356 | } 3357 | catch 3358 | { 3359 | if ($oktaVerbose -eq $true) 3360 | { 3361 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3362 | } 3363 | throw $_ 3364 | } 3365 | return $request 3366 | } 3367 | 3368 | function oktaResetFactorsbyUser() 3369 | { 3370 | param 3371 | ( 3372 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3373 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$uid, 3374 | [parameter(Mandatory=$false)][ValidateLength(1,255)][String]$username 3375 | ) 3376 | if (!$uid) 3377 | { 3378 | if ($username) 3379 | { 3380 | $uid = (oktaGetUserbyID -oOrg $oOrg -userName $username).id 3381 | } else { 3382 | throw ("Must send one of uid or username") 3383 | } 3384 | } 3385 | 3386 | $factors = oktaGetFactorsbyUser -oOrg $oOrg -uid $uid 3387 | $freset = New-Object System.Collections.ArrayList 3388 | foreach ($factor in $factors) 3389 | { 3390 | $_c = $freset.add( (oktaResetFactorbyUser -oOrg $oOrg -uid $uid -fid $factor.id) ) 3391 | $_c = "" 3392 | } 3393 | 3394 | return $freset 3395 | } 3396 | 3397 | function oktaVerifyOTPbyUser() 3398 | { 3399 | param 3400 | ( 3401 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3402 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 3403 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$fid, 3404 | [parameter(Mandatory=$false)][String]$otp 3405 | ) 3406 | 3407 | if ($otp) 3408 | { 3409 | $psobj = @{ passCode = $otp} 3410 | } else { 3411 | $psobj = @{ } 3412 | } 3413 | 3414 | [string]$method = "Post" 3415 | [string]$resource = '/api/v1/users/' + $uid + '/factors/' + $fid + '/verify' 3416 | 3417 | try 3418 | { 3419 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 3420 | } 3421 | catch 3422 | { 3423 | if ($oktaVerbose -eq $true) 3424 | { 3425 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3426 | } 3427 | throw $_ 3428 | } 3429 | return $request 3430 | } 3431 | 3432 | function oktaAuthnQuestionWithState() 3433 | { 3434 | param 3435 | ( 3436 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3437 | [parameter(Mandatory=$true)][ValidateLength(42,42)][String]$stateToken, 3438 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$fid, 3439 | [parameter(Mandatory=$true)][String]$answer 3440 | ) 3441 | 3442 | $psobj = @{ answer = $answer; stateToken = $stateToken } 3443 | 3444 | [string]$method = "Post" 3445 | [string]$resource = '/api/v1/authn/factors/' + $fid + '/verify' 3446 | 3447 | try 3448 | { 3449 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 3450 | } 3451 | catch 3452 | { 3453 | if ($oktaVerbose -eq $true) 3454 | { 3455 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3456 | } 3457 | throw $_ 3458 | } 3459 | return $request 3460 | } 3461 | 3462 | function oktaVerifyMFAnswerbyUser() 3463 | { 3464 | param 3465 | ( 3466 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3467 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$uid, 3468 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$fid, 3469 | [parameter(Mandatory=$true)][String]$answer 3470 | ) 3471 | 3472 | $psobj = @{ answer = $answer} 3473 | 3474 | [string]$method = "Post" 3475 | [string]$resource = '/api/v1/users/' + $uid + '/factors/' + $fid + '/verify' 3476 | 3477 | try 3478 | { 3479 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 3480 | } 3481 | catch 3482 | { 3483 | if ($oktaVerbose -eq $true) 3484 | { 3485 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3486 | } 3487 | throw $_ 3488 | } 3489 | return $request 3490 | } 3491 | 3492 | function oktaVerifyPushbyUser() 3493 | { 3494 | param 3495 | ( 3496 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3497 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$uid, 3498 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$fid, 3499 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$username, 3500 | [parameter(Mandatory=$false)][ValidateLength(7,15)][String]$ClientIP, 3501 | [parameter(Mandatory=$false)][ValidateLength(1,1024)][String]$UserAgent, 3502 | [parameter(Mandatory=$false)][PSCustomObject]$SESSION_STEP_UP 3503 | ) 3504 | 3505 | [string]$method = "Post" 3506 | [bool]$untrusted=$false 3507 | if (! $SESSION_STEP_UP) 3508 | { 3509 | if (!$uid) 3510 | { 3511 | if ($username) 3512 | { 3513 | $uid = (oktaGetUserbyID -oOrg $oOrg -userName $username).id 3514 | } else { 3515 | throw ("Must send one of uid or username") 3516 | } 3517 | } 3518 | } 3519 | 3520 | if (!$fid) 3521 | { 3522 | if ($SESSION_STEP_UP) 3523 | { 3524 | $factors = $SESSION_STEP_UP._embedded.factors 3525 | } else { 3526 | $factors = oktaGetFactorsbyUser -oOrg $oOrg -uid $uid 3527 | } 3528 | $push = $false 3529 | foreach ($factor in $factors) 3530 | { 3531 | if ("push" -eq $factor.factorType) 3532 | { 3533 | $push = $factor 3534 | } 3535 | } 3536 | 3537 | if (!$push) 3538 | { 3539 | throw ("No push factor found for $uid") 3540 | } 3541 | Write-Verbose("Found push factor " + $push.id + " sending push") 3542 | [string]$resource = $push._links.verify.href.Split(".com")[1] 3543 | } else { 3544 | Write-Verbose("Using supplied push factor " + $fid + " sending push") 3545 | [string]$resource = '/api/v1/users/' + $uid + '/factors/' + $fid + '/verify' 3546 | } 3547 | 3548 | if ( ($ClientIP) -or ($UserAgent) ) 3549 | { 3550 | $altHeaders = New-Object System.Collections.Hashtable 3551 | if ($UserAgent) 3552 | { 3553 | $altHeaders.Add('UserAgent', $UserAgent) 3554 | } 3555 | if ($ClientIP) 3556 | { 3557 | $altHeaders.Add('X-Forwarded-For', $ClientIP) 3558 | } 3559 | } 3560 | 3561 | if ($SESSION_STEP_UP) 3562 | { 3563 | $stateToken = $SESSION_STEP_UP.stateToken 3564 | $psobj = @{ stateToken = $stateToken} 3565 | $untrusted=$true 3566 | } else { 3567 | $stateToken=$false 3568 | $psobj = @{} 3569 | } 3570 | 3571 | try 3572 | { 3573 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -altHeaders $altHeaders -body $psobj -untrusted $untrusted 3574 | } 3575 | catch 3576 | { 3577 | if ($oktaVerbose -eq $true) 3578 | { 3579 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3580 | } 3581 | throw $_ 3582 | } 3583 | 3584 | Write-Verbose("Push transaction triggered, pulling for status @ :" + $request._links.poll.href) 3585 | 3586 | $poll = _oktaPollPushLink -factorResult $request -oOrg $oOrg -stateToken $stateToken 3587 | return $poll 3588 | } 3589 | 3590 | function _oktaPollPushLink() 3591 | { 3592 | param 3593 | ( 3594 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3595 | $factorResult, 3596 | $stateToken 3597 | ) 3598 | 3599 | $c = 0 3600 | while ("WAITING" -eq $factorResult.factorResult) 3601 | { 3602 | $c++ 3603 | $sleepy = (2 * ($c/2)) 3604 | Start-Sleep -Seconds $sleepy 3605 | Write-Verbose("Adaptive sleeping for: " + $sleepy + " Seconds") 3606 | if ($factorResult._links.poll.hints) 3607 | { 3608 | [string]$method = $factorResult._links.poll.hints.allow[0] 3609 | [string]$resource = $factorResult._links.poll.href 3610 | } else { 3611 | [string]$method = $factorResult._links.next.hints.allow[0] 3612 | [string]$resource = $factorResult._links.next.href 3613 | } 3614 | if ($stateToken) 3615 | { 3616 | $psobj = @{ stateToken = $stateToken} 3617 | [bool]$untrusted = $true 3618 | } else { 3619 | $psobj = @{} 3620 | [bool]$untrusted = $false 3621 | } 3622 | try 3623 | { 3624 | $factorResult = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj -untrusted $untrusted 3625 | } 3626 | catch 3627 | { 3628 | Write-Verbose($_.TargetObject) 3629 | throw $_ 3630 | } 3631 | if ($factorResult.factorResult) 3632 | { 3633 | Write-Verbose ($factorResult.factorResult) 3634 | } else { 3635 | Write-Verbose ($factorResult.status) 3636 | } 3637 | 3638 | } 3639 | 3640 | <# 3641 | switch ($factorResult.factorResult) 3642 | { 3643 | 3644 | "SUCCESS" 3645 | { 3646 | } 3647 | "REJECTED" 3648 | { 3649 | } 3650 | "TIMEOUT" 3651 | { 3652 | } 3653 | 3654 | 3655 | default {$results = $factorResult} 3656 | } 3657 | #> 3658 | 3659 | return $factorResult 3660 | } 3661 | 3662 | function oktaGetUserSchemabyType() 3663 | { 3664 | param 3665 | ( 3666 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3667 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$tid 3668 | ) 3669 | 3670 | [string]$method = "Get" 3671 | [string]$resource = '/api/v1/user/types/' + $tid + '/schemas' 3672 | 3673 | try 3674 | { 3675 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3676 | } 3677 | catch 3678 | { 3679 | if ($oktaVerbose -eq $true) 3680 | { 3681 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3682 | } 3683 | throw $_ 3684 | } 3685 | return $request 3686 | } 3687 | 3688 | function oktaGetAppSchema() 3689 | { 3690 | param 3691 | ( 3692 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3693 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid 3694 | ) 3695 | 3696 | [string]$method = "Get" 3697 | [string]$resource = '/api/v1/apps/' + $aid + '/user/schemas' 3698 | 3699 | try 3700 | { 3701 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3702 | } 3703 | catch 3704 | { 3705 | if ($oktaVerbose -eq $true) 3706 | { 3707 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3708 | } 3709 | throw $_ 3710 | } 3711 | return $request 3712 | } 3713 | 3714 | function oktaGetAppTypes() 3715 | { 3716 | param 3717 | ( 3718 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3719 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$aid 3720 | ) 3721 | 3722 | [string]$method = "Get" 3723 | [string]$resource = '/api/v1/apps/' + $aid + '/user/types' 3724 | 3725 | try 3726 | { 3727 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3728 | } 3729 | catch 3730 | { 3731 | if ($oktaVerbose -eq $true) 3732 | { 3733 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3734 | } 3735 | throw $_ 3736 | } 3737 | return $request 3738 | } 3739 | 3740 | function oktaGetMapping() 3741 | { 3742 | param 3743 | ( 3744 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3745 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$source, 3746 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$target 3747 | ) 3748 | 3749 | #if (! (($source) -or ($destination)) ) 3750 | #{ 3751 | # throw 'we need something here' 3752 | #} 3753 | 3754 | [string]$method = "Get" 3755 | if (($source) -and ($target)) 3756 | { 3757 | [string]$resource = '/api/internal/v1/mappings?source=' + $source + '&target=' + $target 3758 | } elseif ($source) { 3759 | [string]$resource = '/api/internal/v1/mappings?source=' + $source 3760 | } elseif ($target) { 3761 | [string]$resource = '/api/internal/v1/mappings?target=' + $target 3762 | } else { 3763 | throw 'we need something here' 3764 | } 3765 | 3766 | try 3767 | { 3768 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3769 | } 3770 | catch 3771 | { 3772 | if ($oktaVerbose -eq $true) 3773 | { 3774 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3775 | } 3776 | throw $_ 3777 | } 3778 | return $request 3779 | } 3780 | 3781 | function oktaGetUserSchema() 3782 | { 3783 | param 3784 | ( 3785 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3786 | [parameter(Mandatory=$false)][String]$sid="default" 3787 | ) 3788 | 3789 | [string]$method = "Get" 3790 | [string]$resource = '/api/v1/meta/schemas/user/' + $sid 3791 | 3792 | try 3793 | { 3794 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3795 | } 3796 | catch 3797 | { 3798 | if ($oktaVerbose -eq $true) 3799 | { 3800 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3801 | } 3802 | throw $_ 3803 | } 3804 | return $request 3805 | } 3806 | 3807 | function oktaGetSchemabyID() 3808 | { 3809 | param 3810 | ( 3811 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3812 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$sid 3813 | ) 3814 | 3815 | [string]$method = "Get" 3816 | [string]$resource = '/api/v1/user/schemas/' + $sid 3817 | 3818 | try 3819 | { 3820 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3821 | } 3822 | catch 3823 | { 3824 | if ($oktaVerbose -eq $true) 3825 | { 3826 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3827 | } 3828 | throw $_ 3829 | } 3830 | return $request 3831 | } 3832 | 3833 | function oktaGetTypebyID() 3834 | { 3835 | param 3836 | ( 3837 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3838 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$tid 3839 | ) 3840 | 3841 | [string]$method = "Get" 3842 | [string]$resource = '/api/v1/user/types/' + $tid 3843 | 3844 | try 3845 | { 3846 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3847 | } 3848 | catch 3849 | { 3850 | if ($oktaVerbose -eq $true) 3851 | { 3852 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3853 | } 3854 | throw $_ 3855 | } 3856 | return $request 3857 | } 3858 | 3859 | function oktaGetTypes() 3860 | { 3861 | param 3862 | ( 3863 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg 3864 | ) 3865 | 3866 | [string]$method = "Get" 3867 | [string]$resource = '/api/v1/user/types' 3868 | 3869 | try 3870 | { 3871 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 3872 | } 3873 | catch 3874 | { 3875 | if ($oktaVerbose -eq $true) 3876 | { 3877 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3878 | } 3879 | throw $_ 3880 | } 3881 | return $request 3882 | } 3883 | 3884 | ################## EVENTS ########################### 3885 | 3886 | 3887 | function oktaListEvents() 3888 | { 3889 | param 3890 | ( 3891 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3892 | [int]$limit=1000, 3893 | [boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination, 3894 | [parameter(Mandatory=$false)][ValidateRange(1,180)][int]$sinceDaysAgo=7, 3895 | [parameter(Mandatory=$false)]$since, 3896 | [parameter(Mandatory=$false)]$until, 3897 | [parameter(Mandatory=$false)]$after, 3898 | [parameter(Mandatory=$false)]$filter, 3899 | [parameter(Mandatory=$false)]$startDate, 3900 | [boolean]$publishedFilter=$true 3901 | ) 3902 | 3903 | if ($startDate) 3904 | { 3905 | if ($startDate -is [DateTime]) 3906 | { 3907 | $startDate = Get-Date $startDate.ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 3908 | } else { 3909 | $startDate = Get-Date (Get-Date $startDate).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 3910 | } 3911 | } 3912 | 3913 | if ($since) 3914 | { 3915 | if ($since -is [DateTime]) 3916 | { 3917 | $since = Get-Date $since.ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 3918 | } else { 3919 | $since = Get-Date (Get-Date $since).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 3920 | } 3921 | } else { 3922 | $now = (Get-Date).ToUniversalTime() 3923 | $since = Get-Date ($now.AddDays(($sinceDaysAgo*-1))) -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 3924 | } 3925 | 3926 | if ($filter -and $publishedFilter) 3927 | { 3928 | $filter = $filter + ' and published gt "' + $since + '"' 3929 | } elseif ($publishedFilter) { 3930 | $filter = 'published gt "' + $since + '"' 3931 | } 3932 | 3933 | if ($until -and $publishedFilter) 3934 | { 3935 | if ($until -is [DateTime]) 3936 | { 3937 | $until = Get-Date $until.ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 3938 | } else { 3939 | $until = Get-Date (Get-Date $until).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 3940 | } 3941 | }# elseif ($publishedFilter) { 3942 | # $until = Get-Date (Get-Date).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 3943 | #} 3944 | 3945 | if ($until -and $publishedFilter) 3946 | { 3947 | $filter = $filter + ' and published lt "' + $until + '"' 3948 | } 3949 | 3950 | #$filter = [System.Web.HttpUtility]::UrlPathEncode($filter) 3951 | 3952 | if ($filter -and $publishedFilter) 3953 | { 3954 | [string]$resource = "/api/v1/events?filter=" + $filter + "&limit=" + $limit 3955 | } elseif ($filter -and $startDate) 3956 | { 3957 | [string]$resource = "/api/v1/events?startDate=" + $startDate + "&filter=" + $filter + "&limit=" + $limit 3958 | } elseif ($startDate) 3959 | { 3960 | [string]$resource = "/api/v1/events?startDate" + $startDate + "&limit=" + $limit 3961 | } elseif ($filter) 3962 | { 3963 | [string]$resource = "/api/v1/events?filter=" + $filter + "&limit=" + $limit 3964 | } else { 3965 | [string]$resource = "/api/v1/events?limit=" + $limit 3966 | } 3967 | 3968 | if ($after) 3969 | { 3970 | $resource += "&after=$after" 3971 | } 3972 | [string]$method = "Get" 3973 | 3974 | try 3975 | { 3976 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination $enablePagination -limit $limit 3977 | } 3978 | catch 3979 | { 3980 | if ($oktaVerbose -eq $true) 3981 | { 3982 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 3983 | } 3984 | throw $_ 3985 | } 3986 | return $request 3987 | } 3988 | 3989 | function oktaListLogs() 3990 | { 3991 | param 3992 | ( 3993 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 3994 | [parameter(Mandatory=$false)][ValidateRange(1,1000)][int]$limit, 3995 | [parameter(Mandatory=$false)][ValidateRange(1,180)][int]$sinceDaysAgo, 3996 | [parameter(Mandatory=$false)][ValidateRange(0,180)][int]$untilDaysAgo, 3997 | [parameter(Mandatory=$false)][boolean]$enablePagination=$OktaOrgs[$oOrg].enablePagination, 3998 | [parameter(Mandatory=$false)][string]$since, 3999 | [parameter(Mandatory=$false)][string]$until, 4000 | [parameter(Mandatory=$false)][string]$filter, 4001 | [parameter(Mandatory=$false)][ValidateSet("ASCENDING","DESCENDING")][string]$order, 4002 | [parameter(Mandatory=$false)][string]$next 4003 | ) 4004 | 4005 | [string]$resource = "/api/v1/logs" 4006 | $params = New-Object System.Collections.Hashtable 4007 | $uri = [System.UriBuilder]::new("https", "hostplaceholder", 443, $resource) 4008 | 4009 | if ($limit) 4010 | { 4011 | $params.Add("limit",$limit) 4012 | } 4013 | 4014 | if ($order) 4015 | { 4016 | $params.Add("sortOrder",$order) 4017 | } 4018 | 4019 | if ($since) 4020 | { 4021 | if ($since -is [DateTime]) 4022 | { 4023 | $since = Get-Date $since.ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 4024 | } else { 4025 | $since = Get-Date (Get-Date $since).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 4026 | } 4027 | $params.Add("since",$since) 4028 | } elseif ($sinceDaysAgo) { 4029 | $now = (Get-Date).ToUniversalTime() 4030 | $since = Get-Date ($now.AddDays(($sinceDaysAgo*-1))) -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 4031 | $params.Add("since",$since) 4032 | } 4033 | 4034 | if ($until) 4035 | { 4036 | if ($until -is [DateTime]) 4037 | { 4038 | $until = Get-Date $until.ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 4039 | } else { 4040 | $until = Get-Date (Get-Date $until).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 4041 | } 4042 | $params.Add("until",$until) 4043 | } elseif ($untilDaysAgo) { 4044 | $now = (Get-Date).ToUniversalTime() 4045 | $until = Get-Date ($now.AddDays(($untilDaysAgo*-1))) -Format "yyyy-MM-ddTHH:mm:ss.fffZ" 4046 | $params.Add("until",$until) 4047 | } 4048 | 4049 | if ($filter) 4050 | { 4051 | $params.Add("filter",$filter) 4052 | } 4053 | 4054 | if ($next) 4055 | { 4056 | #test next value first 4057 | if ($next.StartsWith(($OktaOrgs.$oOrg.baseUrl + "/api/v1/logs?"))) 4058 | { 4059 | $resource = $next 4060 | } else { 4061 | _oktaThrowError -text ("This is not a valid next link: " + $next.ToString()) 4062 | } 4063 | } else { 4064 | $uri = oktaBuildURIQuery -uri $uri -addParams $params 4065 | $resource = $uri.Path + $uri.Query 4066 | Write-Verbose("Before: " + $resource) 4067 | $resource = [System.Web.HttpUtility]::UrlPathEncode($resource) 4068 | Write-Verbose(" After: " + $resource) 4069 | } 4070 | 4071 | [string]$method = "Get" 4072 | try 4073 | { 4074 | if ($limit) 4075 | { 4076 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination $enablePagination -limit $limit 4077 | } else { 4078 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -enablePagination $enablePagination 4079 | } 4080 | } 4081 | catch 4082 | { 4083 | if ($oktaVerbose -eq $true) 4084 | { 4085 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4086 | } 4087 | throw $_ 4088 | } 4089 | return $request 4090 | } 4091 | 4092 | ################## Identity Providers ########################### 4093 | 4094 | function oktaListProviders() 4095 | { 4096 | param 4097 | ( 4098 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4099 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$pid, 4100 | [parameter(Mandatory=$false)][ValidateSet('SAML2','FACEBOOK','GOOGLE','LINKEDIN','MICROSOFT')][String]$type, 4101 | [parameter(Mandatory=$false)][ValidateLength(1,255)][String]$filter 4102 | ) 4103 | 4104 | [string]$method = "Get" 4105 | [string]$resource = '/api/v1/idps' 4106 | 4107 | if ($pid) 4108 | { 4109 | $resource += '/' + $pid 4110 | } elseif ($type) 4111 | { 4112 | $resource += '?type=' + $type 4113 | } elseif ($filter) 4114 | { 4115 | $resource += '?q=' + $filter 4116 | } 4117 | 4118 | try 4119 | { 4120 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4121 | } 4122 | catch 4123 | { 4124 | if ($oktaVerbose -eq $true) 4125 | { 4126 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4127 | } 4128 | throw $_ 4129 | } 4130 | return $request 4131 | } 4132 | 4133 | function oktaNewProviderPolicyObject() 4134 | { 4135 | param 4136 | ( 4137 | [parameter(Mandatory=$false)][ValidateSet('AUTO','CALLOUT','DISABLED')][String]$provUserAction='DISABLED', 4138 | [parameter(Mandatory=$false)][bool]$profileMaster=$false, 4139 | [parameter(Mandatory=$false)][ValidateSet('NONE','APPEND','ASSIGN','SYNC')][String]$provGroupAction='NONE', 4140 | [parameter(Mandatory=$false)][ValidateSet('AUTO','CALLOUT','DISABLED')][String]$accountLinkAction='AUTO', 4141 | [parameter(Mandatory=$false)][array]$accountLinkFilter=@(), 4142 | [parameter(Mandatory=$false)][array]$groupsFilter=@(), 4143 | [parameter(Mandatory=$false)][array]$groupsAssign=@(), 4144 | [parameter(Mandatory=$false)][string]$groupSourceAttrName='Groups', 4145 | [parameter(Mandatory=$false)][ValidateLength(9,1024)][String]$userNameTempalate='idpuser.subjectNameId', 4146 | [parameter(Mandatory=$false)][String]$subjectFilter=$null, 4147 | [parameter(Mandatory=$false)][ValidateSet('EMAIL','USERNAME','USERNAME_OR_EMAIL','CUSTOM_ATTRIBUTE')][String]$subjectMatchType='USERNAME_OR_EMAIL', 4148 | [parameter(Mandatory=$false)][String]$subjectMatchAttr=$null, 4149 | [parameter(Mandatory=$false)][String]$maxClockSwew='120000' 4150 | ) 4151 | 4152 | $groups = @{ action = $provGroupAction; sourceAttributeName = $groupSourceAttrName; filter = $groupsFilter; assignments = $groupsAssign } 4153 | $provisioning = @{ action = $provUserAction; profileMaster = $profileMaster; groups = $groups} 4154 | 4155 | if ($accountLinkFilter.Count -ge 1) 4156 | { 4157 | $accountLink = @{ action = $accountLinkAction; filter = @{groups = @{include = $accountLinkFilter }} } 4158 | } else { 4159 | $accountLink = @{ action = $accountLinkAction; filter = $null } 4160 | } 4161 | $userNameTemplateobject = @{ template = $userNameTempalate } 4162 | $subject = @{ userNameTemplate = $userNameTemplateobject; filter = $subjectFilter; matchType = $subjectMatchType; matchAttribute = $subjectMatchAttr } 4163 | 4164 | $policy = @{ provisioning = $provisioning; accountLink = $accountLink; subject = $subject; maxClockSkew = $maxClockSwew } 4165 | 4166 | return $policy 4167 | } 4168 | 4169 | function oktaNewSaml2ProtocolObject() 4170 | { 4171 | param 4172 | ( 4173 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4174 | [parameter(Mandatory=$true)][ValidateLength(20,36)][String]$kid, 4175 | [parameter(Mandatory=$true)][ValidateLength(11,1014)][String]$ssoURL, 4176 | [parameter(Mandatory=$true)][ValidateLength(1,1024)][String]$idpIssuer, 4177 | [parameter(Mandatory=$false)][ValidateLength(1,1024)][String]$idpAudience=($oktaOrgs.$oOrg.baseUrl + '/saml2/service-provider/sp' + (oktaRandLower -Length 18)), 4178 | [parameter(Mandatory=$false)][ValidateLength(1,512)][String]$ssoDestination=$ssoURL, 4179 | [parameter(Mandatory=$false)][ValidateSet('HTTP-POST','HTTP-Redirect')][String]$ssoBinding='HTTP-POST', 4180 | [parameter(Mandatory=$false)][ValidateSet('HTTP-POST','HTTP-Redirect')][String]$acsBinding='HTTP-POST', 4181 | [parameter(Mandatory=$false)][ValidateSet('INSTANCE','ORG')][String]$acsType='INSTANCE', 4182 | [parameter(Mandatory=$false)][ValidateSet('SHA-256','SHA-1')][String]$algoReqAlgo='SHA-256', 4183 | [parameter(Mandatory=$false)][ValidateSet('REQUEST','NONE')][String]$algoReqScope='REQUEST', 4184 | [parameter(Mandatory=$false)][ValidateSet('SHA-256','SHA-1')][String]$algoResAlgo='SHA-256', 4185 | [parameter(Mandatory=$false)][ValidateSet('RESPONSE','ASSERTION','ANY')][String]$algoResScope='ANY', 4186 | [parameter(Mandatory=$false)] 4187 | [ValidateSet('urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', 4188 | 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', 4189 | 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', 4190 | 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')] 4191 | [String]$nameFormat='urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified' 4192 | ) 4193 | 4194 | $endpoints = @{ sso = @{ url = $ssoURL; binding = $ssoBinding; destination = $ssoDestination } 4195 | acs = @{ binding = $acsBinding; type = $acsType } 4196 | } 4197 | 4198 | $credentials = @{ trust = @{ issuer = $idpIssuer; audience = $idpAudience; kid = $kid } 4199 | signing = $null 4200 | } 4201 | 4202 | $alReq = @{ signature = @{ algorithm = $algoReqAlgo; scope = $algoReqScope } } 4203 | $alRes = @{ signature = @{ algorithm = $algoResAlgo; scope = $algoResScope } } 4204 | 4205 | $algorithms = @{ request = $alReq; response = $alRes} 4206 | 4207 | $settings = @{ nameFormat = $nameFormat } 4208 | 4209 | $protocol = @{ type = 'SAML2' 4210 | endpoints = $endpoints 4211 | algorithms = $algorithms 4212 | credentials = $credentials 4213 | settings = $settings 4214 | } 4215 | return $protocol 4216 | } 4217 | 4218 | function oktaAddProvider() 4219 | { 4220 | param 4221 | ( 4222 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4223 | [parameter(Mandatory=$true)][ValidateSet('SAML2','FACEBOOK','GOOGLE','LINKEDIN','MICROSOFT')][String]$type, 4224 | [parameter(Mandatory=$true)][ValidateLength(1,100)][String]$name, 4225 | [parameter(Mandatory=$false)][ValidateSet('INACTIVE','ACTIVE')][string]$status='ACTIVE', 4226 | [parameter(Mandatory=$true)][object]$protocolObject, 4227 | [parameter(Mandatory=$true)][object]$policyObject 4228 | ) 4229 | 4230 | [string]$method = "Post" 4231 | [string]$resource = '/api/v1/idps' 4232 | 4233 | $provider = @{ type = $type 4234 | name = $name 4235 | status = $status 4236 | protocol = $protocolObject 4237 | policy = $policyObject 4238 | } 4239 | 4240 | <# 4241 | $json = $provider | ConvertTo-Json -Depth 10 4242 | 4243 | $prov = ConvertFrom-Json -InputObject $json 4244 | return $prov 4245 | #> 4246 | try 4247 | { 4248 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $provider 4249 | } 4250 | catch 4251 | { 4252 | if ($oktaVerbose -eq $true) 4253 | { 4254 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4255 | } 4256 | throw $_ 4257 | } 4258 | return $request 4259 | } 4260 | 4261 | function oktaDeleteProvider() 4262 | { 4263 | param 4264 | ( 4265 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4266 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$pid 4267 | ) 4268 | 4269 | [string]$method = "Delete" 4270 | [string]$resource = '/api/v1/idps' 4271 | 4272 | $resource += '/' + $pid 4273 | 4274 | try 4275 | { 4276 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4277 | } 4278 | catch 4279 | { 4280 | if ($oktaVerbose -eq $true) 4281 | { 4282 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4283 | } 4284 | throw $_ 4285 | } 4286 | return $request 4287 | } 4288 | 4289 | ################## Identity Provider Keys ########################### 4290 | 4291 | function oktaListProviderKeys() 4292 | { 4293 | param 4294 | ( 4295 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4296 | [parameter(Mandatory=$false)][ValidateLength(20,36)][String]$kid 4297 | ) 4298 | 4299 | [string]$method = "Get" 4300 | [string]$resource = '/api/v1/idps/credentials/keys' 4301 | 4302 | 4303 | 4304 | if ($kid) 4305 | { 4306 | $resource += '/' + $kid 4307 | } 4308 | 4309 | try 4310 | { 4311 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4312 | } 4313 | catch 4314 | { 4315 | if ($oktaVerbose -eq $true) 4316 | { 4317 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4318 | } 4319 | throw $_ 4320 | } 4321 | return $request 4322 | } 4323 | 4324 | function oktaAddProviderKey() 4325 | { 4326 | param 4327 | ( 4328 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4329 | [parameter(Mandatory=$true)][String]$filepath 4330 | ) 4331 | 4332 | [string]$method = "Post" 4333 | [string]$resource = '/api/v1/idps/credentials/keys' 4334 | 4335 | try 4336 | { 4337 | $cert = Get-Content -Path $filepath 4338 | } 4339 | catch 4340 | { 4341 | throw $_.Exception 4342 | } 4343 | 4344 | [string]$x5c = "" 4345 | foreach ($line in $cert) 4346 | { 4347 | if ( ($line -ne '-----BEGIN CERTIFICATE-----') -and ($line -ne '-----END CERTIFICATE-----') ) 4348 | { 4349 | $x5c += ($line) 4350 | } 4351 | } 4352 | $x5cs = @( $x5c ) 4353 | $psobj = @{ x5c = $x5cs } 4354 | 4355 | try 4356 | { 4357 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $psobj 4358 | } 4359 | catch 4360 | { 4361 | if ($oktaVerbose -eq $true) 4362 | { 4363 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4364 | } 4365 | throw $_ 4366 | } 4367 | return $request 4368 | } 4369 | 4370 | function oktaDeleteProviderKey() 4371 | { 4372 | param 4373 | ( 4374 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4375 | [parameter(Mandatory=$true)][ValidateLength(20,36)][String]$kid 4376 | ) 4377 | 4378 | [string]$method = "Delete" 4379 | [string]$resource = '/api/v1/idps/credentials/keys' 4380 | 4381 | $resource += '/' + $kid 4382 | 4383 | try 4384 | { 4385 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4386 | } 4387 | catch 4388 | { 4389 | if ($oktaVerbose -eq $true) 4390 | { 4391 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4392 | } 4393 | throw $_ 4394 | } 4395 | return $request 4396 | } 4397 | 4398 | 4399 | ################## Zones ########################### 4400 | 4401 | function oktaListZones() 4402 | { 4403 | param 4404 | ( 4405 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4406 | [parameter(Mandatory=$false)][ValidateLength(20,20)][String]$zid, 4407 | [parameter(Mandatory=$false)][String]$filter 4408 | ) 4409 | 4410 | [string]$method = "Get" 4411 | [string]$resource = '/api/v1/org/zones' 4412 | 4413 | if ($zid) 4414 | { 4415 | $resource += '/' + $zid 4416 | } 4417 | elseif ($filter) 4418 | { 4419 | $resource += ("?filter=" + $filter) 4420 | } 4421 | 4422 | try 4423 | { 4424 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4425 | } 4426 | catch 4427 | { 4428 | if ($oktaVerbose -eq $true) 4429 | { 4430 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4431 | } 4432 | throw $_ 4433 | } 4434 | return $request 4435 | } 4436 | 4437 | function oktaCreateZone() 4438 | { 4439 | param 4440 | ( 4441 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4442 | [parameter(Mandatory=$false)][ValidateSet("IP")][String]$type="IP", 4443 | [parameter(Mandatory=$true)][ValidateLength(1,128)][String]$name 4444 | ) 4445 | 4446 | [string]$method = "Post" 4447 | [string]$resource = '/api/v1/org/zones' 4448 | 4449 | 4450 | $cidr=@{"type" = "CIDR";"value" = "132.190.0.0/16"} 4451 | $range = @{"type" = "RANGE";"value" = "132.190.192.10"} 4452 | $gateways = @($cidr) 4453 | $proxies = @($range) 4454 | $request = @{ 4455 | type = $type 4456 | name = $name 4457 | status = "ACTIVE" 4458 | system = $false 4459 | id = $null 4460 | created = $null 4461 | lastUpdated = $null 4462 | gateways = $gateways 4463 | proxies = $proxies 4464 | } 4465 | 4466 | try 4467 | { 4468 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $request 4469 | } 4470 | catch 4471 | { 4472 | if ($oktaVerbose -eq $true) 4473 | { 4474 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4475 | } 4476 | throw $_ 4477 | } 4478 | return $request 4479 | } 4480 | 4481 | function oktaCreateApp() 4482 | { 4483 | param 4484 | ( 4485 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4486 | [parameter(Mandatory=$true)][ValidateLength(1,255)][String]$name, 4487 | [parameter(Mandatory=$true)][ValidateLength(1,100)][String]$label, 4488 | [parameter(Mandatory=$true)][ValidateSet("BOOKMARK","BASIC_AUTH","BROWSER_PLUGIN","SECURE_PASSWORD_STORE","SAML_2_0","WS_FEDERATION", 4489 | "AUTO_LOGIN","OPENID_CONNECT","Custom")][String]$signOnMode, 4490 | [parameter(Mandatory=$true)][hashtable]$settings, 4491 | [parameter(Mandatory=$false)][hashtable]$visibility, 4492 | [parameter(Mandatory=$false)][array]$features 4493 | ) 4494 | 4495 | [string]$method = "Post" 4496 | [string]$resource = '/api/v1/apps' 4497 | 4498 | $request = @{ 4499 | name = $name 4500 | label = $label 4501 | status = "ACTIVE" 4502 | settings = $settings 4503 | signOnMode = $signOnMode 4504 | } 4505 | if ($visibility){$request.Add("visibility", $visibility)} 4506 | if ($features){$request.Add("features", $features)} 4507 | 4508 | try 4509 | { 4510 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $request 4511 | } 4512 | catch 4513 | { 4514 | if ($oktaVerbose -eq $true) 4515 | { 4516 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4517 | } 4518 | throw $_ 4519 | } 4520 | return $request 4521 | } 4522 | 4523 | function oktaMakeZoneNet() 4524 | { 4525 | param 4526 | ( 4527 | [parameter(Mandatory=$true)][ValidateSet("CIDR","RANGE")][String]$type, 4528 | [parameter(Mandatory=$true)][String]$address 4529 | ) 4530 | 4531 | $obj = New-Object psobject -Property @{"type" = $type;"value" = $address} 4532 | #$range = @{"type" = "RANGE";"value" = "132.190.192.10"} 4533 | return $obj 4534 | } 4535 | 4536 | function oktaUpdateZone() 4537 | { 4538 | param 4539 | ( 4540 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4541 | [parameter(Mandatory=$true)][ValidateLength(20,20)][String]$zid, 4542 | [parameter(Mandatory=$false)][ValidateLength(1,128)][String]$newName, 4543 | [parameter(Mandatory=$false)][ValidateSet("Add","Remove")][String]$action, 4544 | [parameter(Mandatory=$false)][ValidateSet("gateways","proxies")][String]$section, 4545 | [parameter(Mandatory=$false)][object]$net 4546 | ) 4547 | 4548 | [string]$method = "Put" 4549 | [string]$resource = '/api/v1/org/zones/' + $zid 4550 | 4551 | $current = oktaListZones -zid $zid -oOrg $oOrg 4552 | $eNets = $current.$section 4553 | $newNets = New-Object System.Collections.ArrayList 4554 | $worktoDo=$false 4555 | 4556 | if ($action -eq "Remove") 4557 | { 4558 | foreach ($eNet in $eNets) 4559 | { 4560 | if ( ($net.type -eq $eNet.type) -and ($net.value -eq $eNet.value) ) 4561 | { 4562 | Write-Verbose("Removing " + $eNet.type + " with value of: " + $eNet.value) 4563 | $worktoDo=$true 4564 | } else { 4565 | $_c = $newNets.Add($eNet) 4566 | } 4567 | } 4568 | } 4569 | 4570 | if ($action -eq "Add") 4571 | { 4572 | $worktoDo=$true 4573 | foreach ($eNet in $eNets) 4574 | { 4575 | if ( ($net.type -eq $eNet.type) -and ($net.value -eq $eNet.value) ) 4576 | { 4577 | Write-Verbose("Skipping " + $eNet.type + " with value of: " + $eNet.value) 4578 | $worktoDo=$false 4579 | } else { 4580 | $_c = $newNets.Add($eNet) 4581 | } 4582 | } 4583 | if (($worktoDo) -or ($eNets.Count -lt 1)) 4584 | { 4585 | $_c = $newNets.Add($net) 4586 | $worktoDo=$true 4587 | } 4588 | } 4589 | 4590 | $name = $current.name 4591 | 4592 | if ($newName) 4593 | { 4594 | if (!$newName -eq $current.name) 4595 | { 4596 | $worktoDo = $true 4597 | $name = $newName 4598 | } 4599 | } 4600 | 4601 | if ($section -eq "gateways") 4602 | { 4603 | $otherSection = "proxies" 4604 | } else { 4605 | $otherSection = "gateways" 4606 | } 4607 | 4608 | $request = @{ 4609 | type = $current.type 4610 | name = $name 4611 | system = $current.system 4612 | status = $current.status 4613 | $section = $newNets 4614 | $otherSection= $current.$otherSection 4615 | } 4616 | 4617 | try 4618 | { 4619 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -body $request 4620 | } 4621 | catch 4622 | { 4623 | if ($oktaVerbose -eq $true) 4624 | { 4625 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4626 | } 4627 | throw $_ 4628 | } 4629 | return $request 4630 | } 4631 | 4632 | ################## Orgs ########################### 4633 | 4634 | function oktaListOrgs() 4635 | { 4636 | param 4637 | ( 4638 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4639 | [parameter(Mandatory=$false)][String]$oid 4640 | ) 4641 | 4642 | [string]$method = "Get" 4643 | [string]$resource = '/api/v1/orgs' 4644 | 4645 | 4646 | 4647 | if ($oid) 4648 | { 4649 | $resource += '/' + $oid 4650 | } 4651 | 4652 | try 4653 | { 4654 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4655 | } 4656 | catch 4657 | { 4658 | if ($oktaVerbose -eq $true) 4659 | { 4660 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4661 | } 4662 | throw $_ 4663 | } 4664 | return $request 4665 | } 4666 | 4667 | function oktaListOANApps() 4668 | { 4669 | param 4670 | ( 4671 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4672 | [parameter(Mandatory=$false)][String]$appname 4673 | ) 4674 | 4675 | [string]$method = "Get" 4676 | [string]$resource = '/api/v1/catalog/apps' 4677 | 4678 | 4679 | 4680 | if ($appname) 4681 | { 4682 | $resource += '/' + $appname 4683 | } 4684 | 4685 | try 4686 | { 4687 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4688 | } 4689 | catch 4690 | { 4691 | if ($oktaVerbose -eq $true) 4692 | { 4693 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4694 | } 4695 | throw $_ 4696 | } 4697 | return $request 4698 | } 4699 | 4700 | function oktaListAppsAssignedbyGroupId() 4701 | { 4702 | param 4703 | ( 4704 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4705 | [parameter(Mandatory=$true)][alias("groupId")][ValidateLength(20,20)][String]$gid 4706 | ) 4707 | 4708 | [string]$resource = '/api/v1/groups/' + $gid + '/apps' 4709 | [string]$method = "Get" 4710 | 4711 | try 4712 | { 4713 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4714 | } 4715 | catch 4716 | { 4717 | if ($oktaVerbose -eq $true) 4718 | { 4719 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4720 | } 4721 | throw $_ 4722 | } 4723 | return $request 4724 | } 4725 | 4726 | function oktaListAppAssignments() 4727 | { 4728 | param 4729 | ( 4730 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4731 | [parameter(Mandatory=$false)][String]$other 4732 | ) 4733 | 4734 | [string]$method = "Get" 4735 | [string]$resource = '/api/v1/appInstances' 4736 | 4737 | try 4738 | { 4739 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4740 | } 4741 | catch 4742 | { 4743 | if ($oktaVerbose -eq $true) 4744 | { 4745 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4746 | } 4747 | throw $_ 4748 | } 4749 | return $request 4750 | } 4751 | 4752 | ################## _links ########################### 4753 | 4754 | function oktaFetch_link() 4755 | { 4756 | param 4757 | ( 4758 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4759 | [parameter(Mandatory=$true)][String]$_link 4760 | ) 4761 | 4762 | try 4763 | { 4764 | $request = _oktaNewCall -method "Get" -resource $_link -oOrg $oOrg 4765 | } 4766 | catch 4767 | { 4768 | if ($oktaVerbose -eq $true) 4769 | { 4770 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4771 | } 4772 | throw $_ 4773 | } 4774 | return $request 4775 | } 4776 | 4777 | ################## Policies ########################### 4778 | 4779 | function oktaListPolicies() 4780 | { 4781 | param 4782 | ( 4783 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4784 | [parameter(Mandatory=$false)][int]$limit=20, 4785 | [parameter(Mandatory=$true)][ValidateSet("OKTA_SIGN_ON", "PASSWORD", "MFA_ENROLL")][String]$type, 4786 | [parameter(Mandatory=$false)][switch]$rules, 4787 | [parameter(Mandatory=$false)][string]$pid 4788 | ) 4789 | 4790 | [string]$method = "Get" 4791 | [string]$resource = '/api/v1/policies' 4792 | 4793 | if ($pid) 4794 | { 4795 | $resource += '/' + $pid 4796 | } 4797 | 4798 | $resource += ("?limit=" + $limit) 4799 | 4800 | if ($type) 4801 | { 4802 | $resource += ("&type=" + $type) 4803 | } 4804 | 4805 | if ($rules) 4806 | { 4807 | $resource += "&expand=rules" 4808 | } 4809 | 4810 | try 4811 | { 4812 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg 4813 | } 4814 | catch 4815 | { 4816 | if ($oktaVerbose -eq $true) 4817 | { 4818 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4819 | } 4820 | throw $_ 4821 | } 4822 | return $request 4823 | } 4824 | 4825 | ################## GroupRules ########################### 4826 | 4827 | function oktaListGroupRules() 4828 | { 4829 | param 4830 | ( 4831 | [parameter(Mandatory=$false)][ValidateLength(1,100)][String]$oOrg=$oktaDefOrg, 4832 | [parameter(Mandatory=$false)][int]$limit=50, 4833 | [parameter(Mandatory=$false)][string]$grid 4834 | ) 4835 | 4836 | [string]$method = "Get" 4837 | [string]$resource = '/api/v1/groups/rules' 4838 | 4839 | if ($pid) 4840 | { 4841 | $resource += '/' + $grid 4842 | } 4843 | 4844 | if ($limit) 4845 | { 4846 | $resource += "?limit=$limit" 4847 | } 4848 | 4849 | if ($rules) 4850 | { 4851 | $resource += "&expand=rules" 4852 | } 4853 | 4854 | try 4855 | { 4856 | $request = _oktaNewCall -method $method -resource $resource -oOrg $oOrg -limit $limit 4857 | } 4858 | catch 4859 | { 4860 | if ($oktaVerbose -eq $true) 4861 | { 4862 | Write-Host -ForegroundColor red -BackgroundColor white $_.TargetObject 4863 | } 4864 | throw $_ 4865 | } 4866 | return $request 4867 | } 4868 | 4869 | Export-ModuleMember -Function okta* -Alias okta* 4870 | --------------------------------------------------------------------------------