├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CPM ├── Get-CPMParameterFile.ps1 └── README.md ├── CentralCredentialProvider ├── Get-CCPPassword.Tests.ps1 ├── Get-CCPPassword.ps1 └── README.md ├── ConnectionComponent ├── Backup-ConnectionComponent.ps1 ├── README.md └── Restore-ConnectionComponent.ps1 ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: pspete # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at pete@virtualreal.it. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | All contributions welcomed and are appreciated. 4 | 5 | ## PowerShell Styleguide 6 | 7 | Use the standard *Verb*-*Noun* convention, and only use approved verbs. 8 | 9 | All Functions must have Comment Based Help. 10 | 11 | [K&R (One True Brace Style variant)](https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81) preferred. 12 | 13 | ## Contributing Code 14 | 15 | - Fork the repo. 16 | - Push your changes to your fork. 17 | - Write a [good commit message][commit] 18 | - Submit a pull request 19 | - Keep pull requests limited to a single issue 20 | - Discussion, or necessary changes may be needed before merging the contribution. 21 | 22 | [commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 23 | -------------------------------------------------------------------------------- /CPM/Get-CPMParameterFile.ps1: -------------------------------------------------------------------------------- 1 | Function Get-CPMParameterFile { 2 | <# 3 | .SYNOPSIS 4 | Copies a specific CPM Parameter file from the CPM tmp directory to a specified output folder. 5 | 6 | .DESCRIPTION 7 | Designed to be run locally on a CyberArk CPM Server. 8 | When executed, watches the Password Manager tmp directory for a parameter file related to a CPM operation on 9 | a specified account to be created. 10 | Once found, the parameter file is copied to an output location for further review, or use in CPM plugin debugging 11 | or development. 12 | 13 | .PARAMETER accountName 14 | The name of the account in the vault (not the username). 15 | This is required to be the value from the "Name" property on the Account Details page in PVWA. 16 | 17 | .PARAMETER path 18 | The path to the CPM tmp Directory. 19 | Usually :\Program Files (x86)\CyberArk\Password Manager\tmp 20 | If not specified, path will be built using data from the registry. 21 | 22 | .PARAMETER outputPath 23 | A folder to copy the CPM Parameter file to. 24 | Defaults to the logged on user's MyDocuments folder 25 | 26 | .PARAMETER restartCPMService 27 | Optionally restart the Password Manager Windows Service on the local computer. 28 | 29 | .EXAMPLE 30 | Get-CPMParameterFile -accountName "Operating System-Windows-machine-DomainAdminUser" -Verbose 31 | 32 | Once generated, copies Parameter File relating to account "Operating System-Windows-machine-DomainAdminUser" to the 33 | logged on user's MyDocuments folder. Verbose log messages are displayed. 34 | 35 | .EXAMPLE 36 | Get-CPMParameterFile -accountName "Operating System-unixssh-machine-RootUser23" -outputPath D:\Temp 37 | 38 | Once generated, copies Parameter File relating to account "Operating System-unixssh-machine-RootUser23" to the 39 | D:\Temp folder. 40 | 41 | .EXAMPLE 42 | Get-CPMParameterFile -accountName Application-Cyberark-10.10.10.10-CyberUser -restartCPMService -Verbose 43 | 44 | First, restarts the local Password Manager Service, then, once generated, copies Parameter File relating to account 45 | "Operating System-Windows-machine-DomainAdminUser" to the logged on user's MyDocuments folder. 46 | Verbose log messages are displayed. 47 | 48 | .NOTES 49 | Only intended for execution on a CPM Server. 50 | #> 51 | [CmdletBinding()] 52 | param( 53 | #The name of the account in PVWA 54 | [parameter( 55 | Mandatory = $true 56 | )] 57 | [string]$accountName, 58 | 59 | #:\Program Files (x86)\CyberArk\Password Manager\tmp 60 | #CPM tmp Directory 61 | [parameter( 62 | Mandatory = $false 63 | )] 64 | [ValidateScript( {Test-Path $_})] 65 | [string]$path, 66 | 67 | #Path to copy the file to 68 | [parameter( 69 | Mandatory = $false 70 | )] 71 | [ValidateScript( {Test-Path $_})] 72 | [string]$outputPath = [Environment]::GetFolderPath("MyDocuments"), 73 | 74 | #Whether to restart the CPM Service 75 | [parameter( 76 | Mandatory = $false 77 | )] 78 | [ValidateScript( {Get-Service -Name "CyberArk Password Manager"})] 79 | [switch]$restartCPMService 80 | ) 81 | 82 | Begin { 83 | 84 | Function Get-CPMTempDirectory { 85 | 86 | Try { 87 | 88 | (Join-Path (Get-ItemProperty -EA SilentlyContinue -Path Registry::$( 89 | (Get-ChildItem "HKLM:\SOFTWARE\Wow6432Node\CyberArk\CyberArk Password Manager" -EA SilentlyContinue | 90 | Where-Object {$_.Property -eq "HomeDirectory"} | Sort-Object Name -Descending) | 91 | Select-Object -First 1 -ExpandProperty Name) | 92 | Select-Object -ExpandProperty HomeDirectory) "tmp") 93 | } 94 | 95 | Catch { 96 | 97 | throw "Path to the local \CyberArk\Password Manager\tmp directory not found. Ensure execution is on a CPM server, or specify the correct path." 98 | 99 | } 100 | 101 | } 102 | 103 | } 104 | 105 | Process { 106 | 107 | If(-not($path)) { 108 | 109 | $path = Get-CPMTempDirectory 110 | 111 | } 112 | 113 | Write-Verbose "CPM Directory: $path" 114 | 115 | if($restartCPMService) { 116 | 117 | Try { 118 | 119 | #Find the CPM Service 120 | Get-Service -Name "CyberArk Password Manager" | 121 | Restart-Service -Force -ErrorAction Stop -Verbose 122 | 123 | } 124 | 125 | Catch { 126 | 127 | Write-Error $_ 128 | 129 | } 130 | 131 | Finally { 132 | 133 | Write-Verbose "CyberArk Password Manager Status: $( 134 | (Get-Service "CyberArk Password Manager").Status)" -Verbose 135 | 136 | } 137 | 138 | } 139 | 140 | #Start a timer for progress indication 141 | $elapsedTime = [system.diagnostics.stopwatch]::StartNew() 142 | 143 | do { 144 | 145 | #Search CPM tmp directory for Parameter file 146 | $file = Get-ChildItem -Path $path -File -Filter "*$accountName*" 147 | 148 | Write-Progress -activity "Watching '$path' for '$accountName' Parameter File" -status "$( 149 | [string]::Format("Time Elapsed: {0:d2}:{1:d2}", $elapsedTime.Elapsed.minutes, $elapsedTime.Elapsed.seconds))" 150 | 151 | #stop when found 152 | } until ($file.count -eq 1) 153 | 154 | Write-Verbose "File Found: $($file.Name) ( 155 | $([string]::Format("Time Elapsed: {0:d2}:{1:d2}", $elapsedTime.Elapsed.minutes, $elapsedTime.Elapsed.seconds)))" 156 | 157 | #Copy CPM Parameter file to output directory, output full path 158 | $file.CopyTo((Join-Path $outputPath $file.Name)) | Select-Object -ExpandProperty FullName 159 | 160 | #Stop the timer 161 | $elapsedTime.stop() 162 | 163 | Write-Verbose "File Copied To: $outputPath" 164 | 165 | } 166 | 167 | } -------------------------------------------------------------------------------- /CPM/README.md: -------------------------------------------------------------------------------- 1 | # CPM 2 | 3 | ## Parameter Files 4 | 5 | A method to capture the short lived temporary file containing account configuration parameters which is created on a CyberArk CPM server prior to a password management operation taking place. 6 | 7 | - `Get-CPMParameterFile` 8 | - Watches the CPM `tmp` directory for a parameter file relating a specific account. 9 | - Requires the CyberArk password object name as input. 10 | - Can optionally restart the Password Manager service. 11 | - Found parameter file is copied to an output folder for subsequent use in CPM Plugin development or debugging. -------------------------------------------------------------------------------- /CentralCredentialProvider/Get-CCPPassword.Tests.ps1: -------------------------------------------------------------------------------- 1 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path 2 | $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' 3 | . "$here\$sut" 4 | 5 | Describe "Get-CCPPassword" { 6 | 7 | BeforeEach { 8 | Mock Invoke-RestMethod {} 9 | $InputObj = [pscustomobject]@{ 10 | "AppID" = "SomeApplication" 11 | "URL" = "https://SomeURL" 12 | } 13 | } 14 | 15 | It "sends request" { 16 | $InputObj | Get-CCPPassword 17 | Assert-MockCalled Invoke-RestMethod -Times 1 -Exactly -Scope It 18 | } 19 | 20 | It "sends request with expected method" { 21 | $InputObj | Get-CCPPassword 22 | Assert-MockCalled Invoke-RestMethod -ParameterFilter { 23 | $Method -eq "GET" 24 | 25 | } -Times 1 -Exactly -Scope It 26 | } 27 | 28 | It "sends request with expected content-type" { 29 | $InputObj | Get-CCPPassword 30 | Assert-MockCalled Invoke-RestMethod -ParameterFilter { 31 | $ContentType -eq "application/json" 32 | 33 | } -Times 1 -Exactly -Scope It 34 | } 35 | 36 | It "sends request to expected URL" { 37 | $InputObj | Get-CCPPassword 38 | Assert-MockCalled Invoke-RestMethod -ParameterFilter { 39 | 40 | $URI -eq "https://SomeURL/AIMWebService/api/Accounts?AppID=SomeApplication" 41 | 42 | } -Times 1 -Exactly -Scope It 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /CentralCredentialProvider/Get-CCPPassword.ps1: -------------------------------------------------------------------------------- 1 | function Get-CCPPassword { 2 | <# 3 | .SYNOPSIS 4 | Use the GetPassword REST Web Service to retrieve passwords from the Central Credential Provider. 5 | 6 | .DESCRIPTION 7 | When the Central Credential Provider for Windows is published via an IIS and the Central 8 | Credential Provider Web Service, this function can be used to retrieve credentials. 9 | Passwords stored in the CyberArk Vault are retrieved to the Central Credential Provider, where 10 | they can be accessed by authorized remote applications/scripts using a web service call. 11 | 12 | .PARAMETER AppID 13 | Specifies the unique ID of the application issuing the password request. 14 | 15 | .PARAMETER Safe 16 | Specifies the name of the Safe where the password is stored. 17 | 18 | .PARAMETER Folder 19 | Specifies the name of the folder where the password is stored. 20 | 21 | .PARAMETER Object 22 | Specifies the name of the password object to retrieve. 23 | 24 | .PARAMETER UserName 25 | Defines search criteria according to the UserName account property. 26 | 27 | .PARAMETER Address 28 | Defines search criteria according to the Address account property. 29 | 30 | .PARAMETER Database 31 | Defines search criteria according to the Database account property. 32 | 33 | .PARAMETER PolicyID 34 | Defines the format that will be used in the set PolicyID method. 35 | 36 | .PARAMETER Reason 37 | The reason for retrieving the password. This reason will be audited in the Credential Provider audit log 38 | 39 | .PARAMETER ConnectionTimeout 40 | The number of seconds that the Central Credential Provider will try to retrieve the password. 41 | The timeout is calculated when the request is sent from the web service to the Vault and returned back 42 | to the web service. 43 | 44 | .PARAMETER Credential 45 | Specify the credentials object if OS User authentication is required for CCP. 46 | 47 | .PARAMETER UseDefaultCredentials 48 | Use the default credentials for CCP OS User authentication. 49 | 50 | .PARAMETER WebServiceName 51 | The name the CCP WebService is configured under in IIS. 52 | Defaults to AIMWebService 53 | 54 | .PARAMETER URL 55 | The URL for the CCP Host 56 | 57 | .EXAMPLE 58 | Get-CCPPassword -AppID PSScript -Safe PSAccounts -Object PSPlatform-AccountName -URL https://cyberark.yourcompany.com 59 | 60 | Uses the PSScript App ID to retrieve password for the PSPlatform-AccountName object in the PSAccounts safe from the 61 | https://cyberark.yourcompany.com/AIMWebService CCP Web Service. 62 | 63 | .EXAMPLE 64 | Get-CCPPassword -AppID PowerShell -Safe PSAccounts -UserName svc-psProvision -WebServiceName DevAIM -URL https://cyberark-dev.yourcompany.com 65 | 66 | Uses the PowerShell App ID to search for and retrieve the password for the svc-psProvision account in the PSAccounts safe 67 | from the https://cyberark-dev.yourcompany.com/DevAIM CCP Web Service. 68 | 69 | .EXAMPLE 70 | $result = Get-CCPPassword -AppID PS -Safe PS -Object PSP-AccountName -URL https://cyberark.yourcompany.com 71 | 72 | $result.ToSecureSting() 73 | 74 | Returns the password retrieved from CCP as a Secure String 75 | 76 | .EXAMPLE 77 | $result = Get-CCPPassword -AppID PS -Safe PS -Object PSP-AccountName -URL https://cyberark.yourcompany.com 78 | 79 | $result.ToCredential() 80 | 81 | Returns the username & password retrieved from CCP as a PSCredential object 82 | 83 | .EXAMPLE 84 | Get-CCPPassword -AppID PS -Safe PS -Object PSP-AccountName -URL https://cyberark.yourcompany.com -UseDefaultCredentials 85 | 86 | Calls Invoke-RestMethod with the UseDefaultCredentials switch to use OS User authentication 87 | 88 | .EXAMPLE 89 | Get-CCPPassword -AppID PS -Safe PS -Object PSP-AccountName -URL https://cyberark.yourcompany.com -Credential $creds 90 | 91 | Calls Invoke-RestMethod with the supplied Credentials for OS User authentication 92 | #> 93 | [CmdletBinding(DefaultParameterSetName = "Default")] 94 | Param( 95 | # Unique ID of the application 96 | [Parameter( 97 | Mandatory = $true, 98 | ValueFromPipelineByPropertyName = $true, 99 | ParameterSetName = "Default" 100 | )] 101 | [parameter( 102 | Mandatory = $true, 103 | ValueFromPipeline = $true, 104 | ParameterSetName = "Credential" 105 | )] 106 | [parameter( 107 | Mandatory = $true, 108 | ValueFromPipeline = $true, 109 | ParameterSetName = "DefaultCredentials" 110 | )] 111 | [string] 112 | $AppID, 113 | 114 | # Safe name 115 | [Parameter( 116 | Mandatory = $false, 117 | ValueFromPipelineByPropertyName = $true, 118 | ParameterSetName = "Default" 119 | )] 120 | [parameter( 121 | Mandatory = $false, 122 | ValueFromPipeline = $true, 123 | ParameterSetName = "Credential" 124 | )] 125 | [parameter( 126 | Mandatory = $false, 127 | ValueFromPipeline = $true, 128 | ParameterSetName = "DefaultCredentials" 129 | )] 130 | [string] 131 | $Safe, 132 | 133 | # Folder name 134 | [Parameter( 135 | Mandatory = $false, 136 | ValueFromPipelineByPropertyName = $true, 137 | ParameterSetName = "Default" 138 | )] 139 | [parameter( 140 | Mandatory = $false, 141 | ValueFromPipeline = $true, 142 | ParameterSetName = "Credential" 143 | )] 144 | [parameter( 145 | Mandatory = $false, 146 | ValueFromPipeline = $true, 147 | ParameterSetName = "DefaultCredentials" 148 | )] 149 | [string] 150 | $Folder, 151 | 152 | # Object name 153 | [Parameter( 154 | Mandatory = $false, 155 | ValueFromPipelineByPropertyName = $true, 156 | ParameterSetName = "Default" 157 | )] 158 | [parameter( 159 | Mandatory = $false, 160 | ValueFromPipeline = $true, 161 | ParameterSetName = "Credential" 162 | )] 163 | [parameter( 164 | Mandatory = $false, 165 | ValueFromPipeline = $true, 166 | ParameterSetName = "DefaultCredentials" 167 | )] 168 | [string] 169 | $Object, 170 | 171 | # Search username 172 | [Parameter( 173 | Mandatory = $false, 174 | ValueFromPipelineByPropertyName = $true, 175 | ParameterSetName = "Default" 176 | )] 177 | [parameter( 178 | Mandatory = $false, 179 | ValueFromPipeline = $true, 180 | ParameterSetName = "Credential" 181 | )] 182 | [parameter( 183 | Mandatory = $false, 184 | ValueFromPipeline = $true, 185 | ParameterSetName = "DefaultCredentials" 186 | )] 187 | [string] 188 | $UserName, 189 | 190 | # Search address 191 | [Parameter( 192 | Mandatory = $false, 193 | ValueFromPipelineByPropertyName = $true, 194 | ParameterSetName = "Default" 195 | )] 196 | [parameter( 197 | Mandatory = $false, 198 | ValueFromPipeline = $true, 199 | ParameterSetName = "Credential" 200 | )] 201 | [parameter( 202 | Mandatory = $false, 203 | ValueFromPipeline = $true, 204 | ParameterSetName = "DefaultCredentials" 205 | )] 206 | [string] 207 | $Address, 208 | 209 | # Search database 210 | [Parameter( 211 | Mandatory = $false, 212 | ValueFromPipelineByPropertyName = $true, 213 | ParameterSetName = "Default" 214 | )] 215 | [parameter( 216 | Mandatory = $false, 217 | ValueFromPipeline = $true, 218 | ParameterSetName = "Credential" 219 | )] 220 | [parameter( 221 | Mandatory = $false, 222 | ValueFromPipeline = $true, 223 | ParameterSetName = "DefaultCredentials" 224 | )] 225 | [string] 226 | $Database, 227 | 228 | # SetPolicyID format 229 | [Parameter( 230 | Mandatory = $false, 231 | ValueFromPipelineByPropertyName = $true, 232 | ParameterSetName = "Default" 233 | )] 234 | [parameter( 235 | Mandatory = $false, 236 | ValueFromPipeline = $true, 237 | ParameterSetName = "Credential" 238 | )] 239 | [parameter( 240 | Mandatory = $false, 241 | ValueFromPipeline = $true, 242 | ParameterSetName = "DefaultCredentials" 243 | )] 244 | [string] 245 | $PolicyID, 246 | 247 | # Reason to record in audit log 248 | [Parameter( 249 | Mandatory = $false, 250 | ValueFromPipelineByPropertyName = $true, 251 | ParameterSetName = "Default" 252 | )] 253 | [parameter( 254 | Mandatory = $false, 255 | ValueFromPipeline = $true, 256 | ParameterSetName = "Credential" 257 | )] 258 | [parameter( 259 | Mandatory = $false, 260 | ValueFromPipeline = $true, 261 | ParameterSetName = "DefaultCredentials" 262 | )] 263 | [string] 264 | $Reason, 265 | 266 | # Number of seconds to try 267 | [Parameter( 268 | Mandatory = $false, 269 | ValueFromPipelineByPropertyName = $true, 270 | ParameterSetName = "Default" 271 | )] 272 | [parameter( 273 | Mandatory = $false, 274 | ValueFromPipeline = $true, 275 | ParameterSetName = "Credential" 276 | )] 277 | [parameter( 278 | Mandatory = $false, 279 | ValueFromPipeline = $true, 280 | ParameterSetName = "DefaultCredentials" 281 | )] 282 | [int] 283 | $ConnectionTimeout, 284 | 285 | # Credentials to send in request to CCP 286 | [parameter( 287 | Mandatory = $true, 288 | ValueFromPipeline = $true, 289 | ParameterSetName = "Credential" 290 | )] 291 | [ValidateNotNullOrEmpty()] 292 | [PSCredential] 293 | $Credential, 294 | 295 | # Use current system credentials for request to CCP 296 | [parameter( 297 | Mandatory = $true, 298 | ValueFromPipeline = $true, 299 | ParameterSetName = "DefaultCredentials" 300 | )] 301 | [Switch] 302 | $UseDefaultCredentials, 303 | 304 | # Unique ID of the CCP webservice in IIS 305 | [Parameter( 306 | Mandatory = $false, 307 | ValueFromPipelineByPropertyName = $true, 308 | ParameterSetName = "Default" 309 | )] 310 | [parameter( 311 | Mandatory = $false, 312 | ValueFromPipeline = $true, 313 | ParameterSetName = "Credential" 314 | )] 315 | [parameter( 316 | Mandatory = $false, 317 | ValueFromPipeline = $true, 318 | ParameterSetName = "DefaultCredentials" 319 | )] 320 | [string] 321 | $WebServiceName = "AIMWebService", 322 | 323 | # CCP URL 324 | [Parameter( 325 | Mandatory = $true, 326 | ValueFromPipelineByPropertyName = $true, 327 | ParameterSetName = "Default" 328 | )] 329 | [parameter( 330 | Mandatory = $true, 331 | ValueFromPipeline = $true, 332 | ParameterSetName = "Credential" 333 | )] 334 | [parameter( 335 | Mandatory = $true, 336 | ValueFromPipeline = $true, 337 | ParameterSetName = "DefaultCredentials" 338 | )] 339 | [string] 340 | $URL 341 | ) 342 | 343 | Begin { 344 | 345 | #Collection of parameters which are to be excluded from the request URL 346 | [array]$CommonParameters += [System.Management.Automation.PSCmdlet]::CommonParameters 347 | [array]$CommonParameters += [System.Management.Automation.PSCmdlet]::OptionalCommonParameters 348 | [array]$CommonParameters += "URL", "WebServiceName", "Credential", "UseDefaultCredentials" 349 | 350 | #If Tls12 Security Protocol is available 351 | if(([Net.SecurityProtocolType].GetEnumNames() -contains "Tls12") -and 352 | 353 | #And Tls12 is not already in use 354 | (-not ([System.Net.ServicePointManager]::SecurityProtocol -match "Tls12"))) { 355 | 356 | #Use Tls12 357 | Write-Verbose "Setting Security Protocol to TLS12" 358 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 359 | 360 | } 361 | 362 | } 363 | 364 | Process { 365 | 366 | #Enumerate bound parameters to build query string for URL 367 | $PSBoundParameters.keys | Where-Object {$CommonParameters -notcontains $_} | ForEach-Object { 368 | 369 | [array]$QueryArgs += "$_=$([System.Uri]::EscapeDataString($PSBoundParameters[$_]))" 370 | 371 | } 372 | 373 | #Format URL query string 374 | $Query = $QueryArgs -join '&' 375 | 376 | #Create hashtable of request parameters 377 | $Request = @{ 378 | "URI" = "$URL/$WebServiceName/api/Accounts?$Query" 379 | "Method" = "GET" 380 | "ContentType" = "application/json" 381 | "ErrorAction" = "Stop" 382 | } 383 | 384 | #Add Credential to request is provided 385 | If($($PSCmdlet.ParameterSetName) -eq "Credential") { 386 | 387 | $Request["Credential"] = $Credential 388 | 389 | } 390 | 391 | #Add UseDefaultCredentials switch to request if specified 392 | ElseIf($($PSCmdlet.ParameterSetName) -eq "DefaultCredentials") { 393 | 394 | $Request["UseDefaultCredentials"] = $true 395 | 396 | } 397 | 398 | Try { 399 | 400 | #send request 401 | $result = Invoke-RestMethod @Request 402 | 403 | } Catch { 404 | 405 | try { 406 | 407 | #output error message 408 | $err = $_ | ConvertFrom-Json -ErrorAction SilentlyContinue 409 | Write-Error -Message $err.ErrorMsg -ErrorId $err.ErrorCode 410 | 411 | #if JSON conversion fails throw original exception 412 | } catch {throw $error[-1]} 413 | 414 | #output result 415 | } Finally { 416 | 417 | #Add ScriptMethod to output object to convert password to Secure String 418 | $result | Add-Member -MemberType ScriptMethod -Name ToSecureString -Value { 419 | $this.Content | ConvertTo-SecureString -AsPlainText -Force 420 | } 421 | 422 | #Add ScriptMethod to output object to convert username & password to Credential Object 423 | $result | Add-Member -MemberType ScriptMethod -Name ToCredential -Value { 424 | New-Object System.Management.Automation.PSCredential($this.UserName, $this.ToSecureString()) 425 | } 426 | 427 | #Return the result from CCP 428 | $result 429 | 430 | } 431 | 432 | } 433 | 434 | End {} 435 | 436 | } 437 | -------------------------------------------------------------------------------- /CentralCredentialProvider/README.md: -------------------------------------------------------------------------------- 1 | # Central Credential Provider 2 | 3 | **April 2018**: Now published as the [CredentialRetriever Module](https://github.com/pspete/CredentialRetriever), and available via the [PowerShell Gallery](https://www.powershellgallery.com/packages/CredentialRetriever). 4 | 5 | ## Get Password 6 | 7 | Function to enable retrieval of passwords from the Central Credential Provider. 8 | 9 | - `Get-CCPPassword` 10 | - Uses the Central Credential Provider REST webservice to retrieve passwords. 11 | -------------------------------------------------------------------------------- /ConnectionComponent/Backup-ConnectionComponent.ps1: -------------------------------------------------------------------------------- 1 | function Backup-ConnectionComponent { 2 | <# 3 | .SYNOPSIS 4 | Extracts connection component details from a PVConfiguration.xml file. 5 | Allows configured connection components to be backed up to a file. 6 | 7 | .DESCRIPTION 8 | Individual CyberArk PVWA Connection Component configurations are extracted from the vault without having to 9 | manually manipulate the PVConfiguration.xml file. 10 | Reads a local PVConfiguration.xml file, or fetches a PVConfiguration.xml file from a vault (using PACLI). 11 | Specified connection component details are read from the document and output from the function. 12 | The XML data can be optionally saved to a file in a nominated directory. 13 | Any output files will be named "_.xml" 14 | 15 | .PARAMETER ConnectionComponent 16 | The name, or list of names, of Connection Components for which the configuration is wanted. 17 | 18 | .PARAMETER InputFile 19 | The path to a local copy of a PVConfiguration.xml file from which to read the Connection Component configuration. 20 | 21 | .PARAMETER VaultAddress 22 | The address of the CyberArk vault from which to get the PVConfiguration.xml file. 23 | 24 | .PARAMETER Credential 25 | A credential object with which to connect to the CyberArk Vault. 26 | 27 | .PARAMETER PacliPath 28 | The path to PACLI.EXE 29 | 30 | .PARAMETER PVWAConfigSafe 31 | The name of the CyberArk safe containing PVConfiguration.xml. 32 | 33 | .PARAMETER OutputDirectory 34 | The path to a local folder in which to optionally save individual backup files containing connection component 35 | configurations. 36 | 37 | .EXAMPLE 38 | Backup-ConnectionComponent -ConnectionComponent SSH -InputFile C:\PVConfiguration.xml 39 | 40 | Extracts the SSH connection component details from a local PVConfiguration.xml file. 41 | 42 | .EXAMPLE 43 | Backup-ConnectionComponent -ConnectionComponent SSH -VaultAddress EPV01 -Credential $cred -PacliFolder C:\PACLI 44 | 45 | Extracts the SSH connection component details from PVConfiguration.xml file for the CyberArk vault EPV01. 46 | 47 | .EXAMPLE 48 | Backup-ConnectionComponent -ConnectionComponent SSH,RDP -VaultAddress 10.10.10.20 -Credential $cred ` 49 | -PacliFolder C:\PACLI -OutputDirectory .\ 50 | 51 | Extracts the SSH connection component details from PVConfiguration.xml file for the CyberArk vault EPV01. 52 | Saves connection component configurations to local files. 53 | 54 | .NOTES 55 | V 1.0.0+ of PoShPACLI Module is required on the local machine 56 | https://github.com/pspete/PoShPACLI 57 | 58 | #> 59 | 60 | #Requires -Module PoShPACLI 61 | [CmdletBinding()] 62 | Param( 63 | 64 | # Connection Component Name 65 | [Parameter( 66 | Mandatory = $true, 67 | ValueFromPipelineByPropertyName = $false, 68 | HelpMessage = "The name of the connection component" 69 | )] 70 | [ValidateNotNullOrEmpty()] 71 | [string[]] 72 | $ConnectionComponent, 73 | 74 | # Specifies the path to a PVWAConfiguration.XML file. 75 | [Parameter( 76 | Mandatory = $true, 77 | ParameterSetName = "FromFile", 78 | ValueFromPipelineByPropertyName = $false, 79 | HelpMessage = "Path to local PVConfiguration.xml file" 80 | )] 81 | [ValidateNotNullOrEmpty()] 82 | [ValidateScript( { Select-XML -Path $_ -XPath "//ConnectionComponents" } )] 83 | [string] 84 | $InputFile, 85 | 86 | # IP or DNS address of CyberArk Vault Server 87 | [Parameter( 88 | Mandatory = $true, 89 | ParameterSetName = "Default", 90 | ValueFromPipelineByPropertyName = $false, 91 | HelpMessage = "IP or DNS address of CyberArk Vault Server" 92 | )] 93 | [ValidateNotNullOrEmpty()] 94 | [string] 95 | $VaultAddress, 96 | 97 | # Credentials used to logon to the CyberArkVault 98 | [Parameter( 99 | Mandatory = $true, 100 | ParameterSetName = "Default", 101 | ValueFromPipelineByPropertyName = $false, 102 | HelpMessage = "Vault Credentials" 103 | )] 104 | [ValidateNotNullOrEmpty()] 105 | [pscredential] 106 | $Credential, 107 | 108 | # PACLI.EXE 109 | [Parameter( 110 | Mandatory = $true, 111 | ParameterSetName = "Default", 112 | ValueFromPipelineByPropertyName = $false, 113 | HelpMessage = "Path to PACLI.EXE." 114 | )] 115 | [ValidateNotNullOrEmpty()] 116 | [ValidateScript( { Test-Path $_ } )] 117 | [string] 118 | $PacliPath, 119 | 120 | # PVWAConfig Safe Name 121 | [Parameter( 122 | Mandatory = $false, 123 | ParameterSetName = "Default", 124 | ValueFromPipelineByPropertyName = $false, 125 | HelpMessage = "Name of the safe containing PVConfiguration.xml" 126 | )] 127 | [ValidateNotNullOrEmpty()] 128 | [string] 129 | $PVWAConfigSafe = "PVWAConfig", 130 | 131 | # Specifies a file path to output connection component data to. 132 | [Parameter( 133 | Mandatory = $false, 134 | ValueFromPipelineByPropertyName = $false, 135 | HelpMessage = "Path to folder in which to save output files." 136 | )] 137 | [ValidateNotNullOrEmpty()] 138 | [string] 139 | $OutputDirectory 140 | 141 | ) 142 | 143 | Begin { 144 | 145 | if ($PsCmdlet.ParameterSetName -eq "Default") { 146 | 147 | #tasks for PACLI operation 148 | Try { 149 | 150 | #Initialise 151 | Set-PVConfiguration -ClientPath $PacliPath -ErrorAction Stop | Out-Null 152 | 153 | if (-not (Get-Process PACLI -ErrorAction SilentlyContinue)) { 154 | 155 | Start-PVPACLI -ErrorAction Stop | Out-Null 156 | 157 | } 158 | 159 | } 160 | 161 | Catch { 162 | 163 | #Terminate on any error - cannot continue if PACLI process not available 164 | Throw $_ 165 | 166 | } 167 | 168 | Try { 169 | 170 | Write-Verbose "Connecting to Vault: $VaultAddress" 171 | 172 | #Logon to Vault, to get token, open target safe 173 | $token = New-PVVaultDefinition -address $VaultAddress -vault Source | 174 | Connect-PVVault -user $($Credential.UserName) -password $($Credential.Password) -ErrorAction Stop | 175 | Open-PVSafe -safe $PVWAConfigSafe -ErrorAction Stop 176 | 177 | Write-Verbose "Downloading Input File: PVConfiguration.xml" 178 | 179 | #Save PVConfiguration.xml to Local Temp folder 180 | $token | 181 | Get-PVFile -folder Root -file PVConfiguration.xml ` 182 | -localFolder $env:TEMP -localFile _bak_PVConfiguration.xml -ErrorAction Stop | Out-Null 183 | 184 | #Set inputfile path to local copy of PVConfiguration.xml 185 | $InputFile = Join-Path $env:TEMP "_bak_PVConfiguration.xml" 186 | 187 | } 188 | 189 | Catch { 190 | 191 | #Attempt Logoff & Stop 192 | $token | Disconnect-PVVault -ErrorAction SilentlyContinue | 193 | Stop-PVPacli | Out-Null 194 | 195 | #Terminate on any error - cannot continue if PACLI process does not succeed 196 | Throw $_ 197 | 198 | } 199 | 200 | Finally { 201 | 202 | #Close Safe, Logoff 203 | $token | 204 | Close-PVSafe -safe $PVWAConfigSafe -ErrorAction SilentlyContinue | 205 | Disconnect-PVVault | Out-Null 206 | 207 | } 208 | 209 | } 210 | 211 | Write-Verbose "Importing Input File: $InputFile" 212 | 213 | #Import PVConfiguration.xml file 214 | $Config = Select-Xml -Path $InputFile -XPath / 215 | 216 | } 217 | 218 | Process { 219 | 220 | foreach ($ComponentName in $ConnectionComponent) { 221 | 222 | If ($Component = (($Config | Select-Xml -XPath "//ConnectionComponent[@Id='$ComponentName']").Node)) { 223 | 224 | Write-Verbose "Connection Component Found: $ComponentName" 225 | 226 | #if output directory specified 227 | If ($OutputDirectory) { 228 | 229 | #Write XML to file in directory 230 | $Component.OuterXML | Out-File -FilePath ( 231 | Join-Path $OutputDirectory "_$($Component.Id).xml") -Encoding utf8 232 | 233 | Write-Verbose "Saving '_$($Component.Id).xml' to $(Get-Item $OutputDirectory)" 234 | 235 | } 236 | 237 | #output collection 238 | Write-Output $Component 239 | 240 | } 241 | 242 | #connection component not found 243 | Else { 244 | 245 | #output error 246 | Write-Error "Connection Component Not Found: $ComponentName" 247 | 248 | } 249 | 250 | } 251 | 252 | } 253 | 254 | End { 255 | 256 | #If file fetched from vault, and retrieved file exists locally 257 | if (($PsCmdlet.ParameterSetName -eq "Default") -and (Test-Path $InputFile)) { 258 | 259 | if (Get-Process PACLI -ErrorAction SilentlyContinue) { 260 | 261 | Write-Verbose "Stopping Pacli" 262 | 263 | Stop-PVPACLI -ErrorAction SilentlyContinue | Out-Null 264 | 265 | } 266 | 267 | Write-Verbose "Deleting $InputFile" 268 | 269 | #Clean Up 270 | Remove-Item $InputFile 271 | 272 | } 273 | 274 | } 275 | 276 | } -------------------------------------------------------------------------------- /ConnectionComponent/README.md: -------------------------------------------------------------------------------- 1 | # Connection Components 2 | 3 | ## Backup & Restore 4 | 5 | These functions provide methods to save connection component customisations to individual files for backup, and restore connection components from these files. 6 | 7 | [`PoShPACLI`](https://github.com/pspete/PoShPACLI) (Version 1.0.0+) & `PACLI.EXE` are required. 8 | 9 | - `Backup-ConnectionComponent` 10 | - Extracts connection component details from a PVConfiguration.xml file. 11 | - Any configured connection components can be backed up to file. 12 | 13 | - `Restore-ConnectionComponent` 14 | - Restores a "ConnectionComponent" to a CyberArk PVConfiguration.xml file. 15 | -------------------------------------------------------------------------------- /ConnectionComponent/Restore-ConnectionComponent.ps1: -------------------------------------------------------------------------------- 1 | function Restore-ConnectionComponent { 2 | <# 3 | .SYNOPSIS 4 | Restores (adds or replaces) a "ConnectionComponent" in a CyberArk PVConfiguration.xml file. 5 | 6 | .DESCRIPTION 7 | When passed xml objects, or xml files, containing data for a connection component configuration, the data will be used 8 | to update a PVConfiguration.xml file. 9 | 10 | The PVConfiguration.xml file can either be a local copy, or be automatically retrieved from, updated & saved, and 11 | then stored back in a CyberArk Vault using PACLI (and relevant vault credentials). 12 | 13 | If the Connection Component being restored does not currently exist in the PVConfiguration.xml file, it will be 14 | added as an additional connection component. If a connection component with the same Id already exists in the 15 | PVConfiguration.xml file, the existing connection component will be replaced. 16 | 17 | Restore-ConnectionComponent is a companion function to Backup-ConnectionComponent; It can consume pipeline output 18 | or backup files created by Backup-ConnectionComponent, ideal for transferring connection components developed in 19 | one environment to other environments for testing or deployment, or reverting to known good configurations. 20 | 21 | .PARAMETER ConnectionComponent 22 | XML object containing a Connection Component Element from PVConfiguration.xml. 23 | The Output of Backup-ConnectionComponent is expected. 24 | 25 | .PARAMETER BackupFile 26 | An xml file containing Connection Component configuration element. 27 | A file should contain only data for a single connection component. 28 | Backup file from Backup-ConnectionComponent is expected. 29 | 30 | .PARAMETER LocalConfig 31 | A local PVConfiguration.xml file to update. 32 | 33 | .PARAMETER VaultAddress 34 | The address of a CyberArk vault containing a PVConfiguration.xml file to update. 35 | 36 | .PARAMETER Credential 37 | Username/password to authenticate to the CyberArk vault. 38 | 39 | .PARAMETER PacliPath 40 | Path to PACLI.exe. 41 | 42 | .PARAMETER PVWAConfigSafe 43 | The name of the safe in the CyberArk vault containing the PVConfiguration.xml file. 44 | Defaults to PVWAConfig. 45 | 46 | .EXAMPLE 47 | Restore-ConnectionComponent -ConnectionComponent $SSH -LocalConfig C:\PVConfiguration.xml 48 | 49 | Restores Connection Component (stored in $SSH) to Local PVConfiguration file. 50 | 51 | .EXAMPLE 52 | Restore-ConnectionComponent -ConnectionComponent $RDP -VaultAddress QAEPV -Credential $QACred -PacliFolder C:\PACLI 53 | 54 | Restores Connection Component (stored in $RDP) to PVConfiguration file in PVWAConfig safe in Vault QAEPV. 55 | 56 | .EXAMPLE 57 | Restore-ConnectionComponent -BackupFile C:\_PSM-RDP.xml -LocalConfig C:\PVConfiguration.xml 58 | 59 | Restores connection component from local backup file _PSM-RDP.xml to local PVConfiguration file. 60 | 61 | .EXAMPLE 62 | Restore-ConnectionComponent -BackupFile C:\_Web.xml -VaultAddress Prod-EPV -Credential $Creds -PacliFolder C:\PACLI 63 | 64 | Restores connection component from local backup file _Web.xml to Vault Prod-EPV. 65 | 66 | .EXAMPLE 67 | Backup-ConnectionComponent -ConnectionComponent SSH -VaultAddress EPV01 -Credential $cred -PacliFolder C:\PACLI | 68 | Restore-ConnectionComponent -LocalConfig C:\PVConfiguration.xml 69 | 70 | Restores SSH Connection Component output by Backup-ConnectionComponent to local PVConfiguration file. 71 | 72 | .EXAMPLE 73 | Backup-ConnectionComponent -ConnectionComponent RDP -VaultAddress EPV01 -Credential $cred1 -PacliFolder C:\PACLI | 74 | Restore-ConnectionComponent -VaultAddress EPV02 -Credential $cred2 -PacliFolder C:\PACLI 75 | 76 | Restores RDP Connection Component from Vault EPV01, to PVConfiguration.xml in vault EPV02. 77 | 78 | .NOTES 79 | PoShPACLI Module is required to be available on the local machine 80 | https://github.com/pspete/PoShPACLI 81 | 82 | #> 83 | 84 | #Requires -Module PoShPACLI 85 | [CmdletBinding()] 86 | param( 87 | # Connection Component Name 88 | [Parameter( 89 | Mandatory = $true, 90 | ParameterSetName = "Default", 91 | ValueFromPipeline = $true, 92 | ValueFromPipelineByPropertyName = $false, 93 | HelpMessage = "XML object containing Connection Component configuration" 94 | )] 95 | [Parameter( 96 | Mandatory = $true, 97 | ParameterSetName = "LocalFile", 98 | ValueFromPipeline = $true, 99 | ValueFromPipelineByPropertyName = $false, 100 | HelpMessage = "XML object containing Connection Component configuration" 101 | )] 102 | [ValidateNotNullOrEmpty()] 103 | [System.Xml.XmlElement[]] 104 | $ConnectionComponent, 105 | 106 | # Connection Component Backup XML file(s). 107 | [Parameter( 108 | Mandatory = $false, 109 | ParameterSetName = "FileToRemote", 110 | ValueFromPipelineByPropertyName = $false, 111 | HelpMessage = "Connection Component Backup XML file path" 112 | )] 113 | [Parameter( 114 | Mandatory = $false, 115 | ParameterSetName = "FileToLocal", 116 | ValueFromPipelineByPropertyName = $false, 117 | HelpMessage = "Connection Component Backup XML file path" 118 | )] 119 | [ValidateNotNullOrEmpty()] 120 | [ValidateScript( { Select-XML -Path $_ -XPath "//ConnectionComponent" } )] 121 | [string[]] 122 | $BackupFile, 123 | 124 | # Local PVConfiguration.xml file. 125 | [Parameter( 126 | Mandatory = $false, 127 | ParameterSetName = "LocalFile", 128 | ValueFromPipelineByPropertyName = $false, 129 | HelpMessage = "Local PVConfiguration.xml file to update" 130 | )] 131 | [Parameter( 132 | Mandatory = $false, 133 | ParameterSetName = "FileToLocal", 134 | ValueFromPipelineByPropertyName = $false, 135 | HelpMessage = "Path to local PVConfiguration.xml file to update" 136 | )] 137 | [ValidateNotNullOrEmpty()] 138 | [ValidateScript( { Select-XML -Path $_ -XPath "//ConnectionComponents" } )] 139 | [string[]] 140 | $LocalConfig, 141 | 142 | # IP or DNS address of CyberArk Vault Server 143 | [Parameter( 144 | Mandatory = $true, 145 | ParameterSetName = "Default", 146 | ValueFromPipelineByPropertyName = $false, 147 | HelpMessage = "IP or DNS address of CyberArk Vault Server" 148 | )] 149 | [Parameter( 150 | Mandatory = $true, 151 | ParameterSetName = "FileToRemote", 152 | ValueFromPipelineByPropertyName = $false, 153 | HelpMessage = "IP or DNS address of CyberArk Vault Server" 154 | )] 155 | [ValidateNotNullOrEmpty()] 156 | [string] 157 | $VaultAddress, 158 | 159 | # Credentials used to logon to the CyberArkVault 160 | [Parameter( 161 | Mandatory = $true, 162 | ParameterSetName = "Default", 163 | ValueFromPipelineByPropertyName = $false, 164 | HelpMessage = "Vault Credentials" 165 | )] 166 | [Parameter( 167 | Mandatory = $true, 168 | ParameterSetName = "FileToRemote", 169 | ValueFromPipelineByPropertyName = $false, 170 | HelpMessage = "Vault Credentials" 171 | )] 172 | [ValidateNotNullOrEmpty()] 173 | [pscredential] 174 | $Credential, 175 | 176 | # PACLI.EXE Path 177 | [Parameter( 178 | Mandatory = $true, 179 | ParameterSetName = "Default", 180 | ValueFromPipelineByPropertyName = $false, 181 | HelpMessage = "Path to PACLI.EXE." 182 | )] 183 | [Parameter( 184 | Mandatory = $true, 185 | ParameterSetName = "FileToRemote", 186 | ValueFromPipelineByPropertyName = $false, 187 | HelpMessage = "Path to PACLI.EXE." 188 | )] 189 | [ValidateNotNullOrEmpty()] 190 | [ValidateScript( { Test-Path $_ } )] 191 | [string] 192 | $PacliPath, 193 | 194 | # PVWAConfig Safe Name 195 | [Parameter( 196 | Mandatory = $false, 197 | ParameterSetName = "Default", 198 | ValueFromPipelineByPropertyName = $false, 199 | HelpMessage = "Name of the safe containing PVConfiguration.xml" 200 | )] 201 | [Parameter( 202 | Mandatory = $false, 203 | ParameterSetName = "FileToRemote", 204 | ValueFromPipelineByPropertyName = $false, 205 | HelpMessage = "Name of the safe containing PVConfiguration.xml" 206 | )] 207 | [ValidateNotNullOrEmpty()] 208 | [string] 209 | $PVWAConfigSafe = "PVWAConfig" 210 | ) 211 | 212 | Begin { 213 | 214 | #If PACLI is required (for Retrieve or Store of remote PVConfiguration.xml) 215 | if (($PsCmdlet.ParameterSetName -eq "Default") -or ($PsCmdlet.ParameterSetName -eq "FileToRemote")) { 216 | 217 | Try { 218 | 219 | #Initialise 220 | Set-PVConfiguration -ClientPath $PacliPath -ErrorAction Stop | Out-Null 221 | 222 | #If Pacli not already running 223 | if (-not (Get-Process PACLI -ErrorAction SilentlyContinue)) { 224 | 225 | #Start Pacli 226 | Start-PVPACLI -ErrorAction Stop | Out-Null 227 | 228 | } 229 | 230 | } 231 | 232 | Catch { 233 | 234 | #Terminate on any error - cannot continue if PACLI process not available 235 | Throw $_ 236 | 237 | } 238 | 239 | Try { 240 | 241 | Write-Verbose "Connecting to Vault: $VaultAddress" 242 | 243 | #Logon to Vault, to get token, open target safe 244 | $token = New-PVVaultDefinition -address $VaultAddress -vault Destination -ErrorAction SilentlyContinue | 245 | Connect-PVVault -user $($Credential.UserName) -password $($Credential.Password) -ErrorAction Stop | 246 | Open-PVSafe -safe $PVWAConfigSafe -ErrorAction Stop 247 | 248 | Write-Verbose "Downloading Target File: PVConfiguration.xml" 249 | 250 | #Save PVConfiguration.xml to Local Temp folder 251 | $token | 252 | Get-PVFile -folder Root -file PVConfiguration.xml ` 253 | -localFolder $env:TEMP -localFile _dst_PVConfiguration.xml -ErrorAction Stop | Out-Null 254 | 255 | 256 | #Set inputfile path to local copy of PVConfiguration.xml 257 | $PVConfiguration = Join-Path $env:TEMP "_dst_PVConfiguration.xml" 258 | 259 | } 260 | 261 | Catch { 262 | 263 | #Attempt Logoff & Stop 264 | $token | Disconnect-PVVault -ErrorAction SilentlyContinue | 265 | Stop-PVPacli -ErrorAction SilentlyContinue | Out-Null 266 | 267 | #Terminate on any error - cannot continue if PACLI process does not succeed 268 | Throw $_ 269 | 270 | } 271 | 272 | } 273 | 274 | if (($PsCmdlet.ParameterSetName -eq "FileToLocal") -or ($PsCmdlet.ParameterSetName -eq "LocalFile")) { 275 | 276 | #Set inputfile path to local PVConfiguration.xml 277 | $PVConfiguration = $LocalConfig 278 | 279 | } 280 | 281 | Write-Verbose "Importing Target File: $PVConfiguration" 282 | 283 | #Import PVConfiguration.xml data 284 | $Config = (Select-Xml -Path $PVConfiguration -XPath / ).Node 285 | 286 | } 287 | 288 | Process { 289 | 290 | #If Restoring from Backup Files 291 | if (($PsCmdlet.ParameterSetName -eq "FileToLocal") -or ($PsCmdlet.ParameterSetName -eq "FileToRemote")) { 292 | 293 | #Enumerate files 294 | foreach ($File in $BackupFile) { 295 | 296 | Write-Verbose "Importing Backup File: $File" 297 | 298 | #Add ConnectionComponent XML data to array 299 | $ConnectionComponent += ((Select-Xml -Path $File -XPath / ).node).ConnectionComponent 300 | 301 | } 302 | 303 | } 304 | 305 | #Process each Component to Restore 306 | foreach ($Component in $ConnectionComponent) { 307 | 308 | #Current Connection Components 309 | $ConnectionComponents = $Config.PasswordVaultConfiguration.ConnectionComponents 310 | 311 | Write-Verbose "Restoring Connection Component: $($Component.Id)" 312 | 313 | Try { 314 | 315 | #Import Component as node of config to update 316 | $NewNode = $Config.PasswordVaultConfiguration.OwnerDocument.ImportNode($Component, $true) 317 | 318 | #If Component already exists 319 | if ($OldNode = $ConnectionComponents.SelectSingleNode("//ConnectionComponent[@Id='$($Component.Id)']")) { 320 | 321 | Write-Verbose "Replacing Connection Component Node: $($Component.Id)" 322 | 323 | #Replace Node 324 | $Config.PasswordVaultConfiguration.ConnectionComponents.ReplaceChild($NewNode, $OldNode) | Out-Null 325 | 326 | } 327 | 328 | #Connection Component does not exist 329 | Else { 330 | 331 | Write-Verbose "Adding Connection Component Node: $($Component.Id)" 332 | 333 | #Append Connection Component Node 334 | $Config.PasswordVaultConfiguration.ConnectionComponents.AppendChild($NewNode) | Out-Null 335 | 336 | } 337 | 338 | } 339 | 340 | Catch { 341 | 342 | Write-Error $_ 343 | 344 | } 345 | 346 | Finally { 347 | 348 | Write-Verbose "Saving File: $($PVConfiguration | Get-Item).FullName" 349 | 350 | #Normalize XML 351 | $Config.Normalize() 352 | 353 | #Update local PVConfiguration.xml 354 | $Config.Save(($PVConfiguration | Get-Item).FullName) 355 | 356 | } 357 | 358 | } 359 | 360 | #If Storing file back in a vault 361 | if (($PsCmdlet.ParameterSetName -eq "Default") -or ($PsCmdlet.ParameterSetName -eq "FileToRemote")) { 362 | 363 | #upload file 364 | Try { 365 | 366 | Write-Verbose "Uploading PVConfiguration.xml to $PVWAConfigSafe" 367 | 368 | #Store Updated local PVConfiguration.xml to PVConfig Safe. 369 | $token | 370 | Add-PVFile -folder Root -file PVConfiguration.xml ` 371 | -localFolder $env:TEMP -localFile _dst_PVConfiguration.xml -ErrorAction Stop | Out-Null 372 | 373 | } 374 | 375 | Catch { 376 | 377 | #Try Close Safe, Logoff, Stop Pacli 378 | $token | Close-PVSafe -ErrorAction SilentlyContinue | 379 | Disconnect-PVVault | Stop-PVPacli | Out-Null 380 | 381 | #Terminate on any error - cannot continue if PACLI process does not succeed 382 | Throw $_ 383 | 384 | } 385 | 386 | } 387 | 388 | } 389 | 390 | End { 391 | 392 | #If PACLI has been required 393 | if (($PsCmdlet.ParameterSetName -eq "Default") -or ($PsCmdlet.ParameterSetName -eq "FileToRemote")) { 394 | 395 | #Check for PACLI process 396 | if (Get-Process PACLI -ErrorAction SilentlyContinue) { 397 | 398 | Write-Verbose "Stopping Pacli" 399 | 400 | #Close Safe, Logoff, Always (try to) Stop Pacli 401 | $token | Close-PVSafe -safe $PVWAConfigSafe -ErrorAction SilentlyContinue | 402 | Disconnect-PVVault -ErrorAction SilentlyContinue | 403 | Stop-PVPacli -ErrorAction SilentlyContinue | Out-Null 404 | 405 | } 406 | 407 | Write-Verbose "Deleting $PVConfiguration" 408 | 409 | #Clean Up - Delete Retrieved File 410 | Remove-Item $PVConfiguration 411 | 412 | } 413 | 414 | } 415 | 416 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Pete Maan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CyberArk PowerTools 2 | 3 | PowerShell scripts for CyberArk Tasks & Operations. 4 | 5 | **Requests accepted** - if there is a script you would like to see for a CyberArk task, log an issue and we can see what can be done. --------------------------------------------------------------------------------