diff --git a/Modules/VISecret/README.md b/Modules/VISecret/README.md new file mode 100644 index 0000000..ca48cc8 --- /dev/null +++ b/Modules/VISecret/README.md @@ -0,0 +1,7 @@ +# Example module for using SecretManagement and SecretStore to save PowerCLI credentials + + + +This module demonstrates how users can use the the Microsoft.PowerShell.SecretManagement and Microsoft.PowerShell.SecretStore modules to save their PowerCLI credentials. + +The module supports PowerShell 5.1 and PowerShell 7.0 and above. \ No newline at end of file diff --git a/Modules/VISecret/VMware.VISecret.psd1 b/Modules/VISecret/VMware.VISecret.psd1 new file mode 100644 index 0000000..47334c5 --- /dev/null +++ b/Modules/VISecret/VMware.VISecret.psd1 @@ -0,0 +1,138 @@ +# +# Module manifest for module 'VMware.VISecret' +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'VMware.VISecret.psm1' + + # Version number of this module. + ModuleVersion = '1.0.0.0' + + # Supported PSEditions + CompatiblePSEditions = @('Desktop', 'Core') + + # ID used to uniquely identify this module + GUID = '66124b00-4095-4a1f-9940-f91622009b15' + + # Author of this module + Author = 'VMware' + + # Company or vendor of this module + CompanyName = 'VMware' + + # Copyright statement for this module + Copyright = 'Copyright (c) VMware, Inc. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'Module to enable easy use of Microsoft.PowerShell.SecretManagement module in VMware context' + + # Minimum version of the PowerShell engine required by this module + PowerShellVersion = '5.1' + + # Name of the PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # ClrVersion = '' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + RequiredModules = @( + @{"ModuleName"="VMware.VimAutomation.Core";"ModuleVersion"="1.0.0.0"} + @{"ModuleName"="Microsoft.PowerShell.SecretManagement";"ModuleVersion"="1.1.2"} + @{"ModuleName"="Microsoft.PowerShell.SecretStore";"ModuleVersion"="1.0.6"} + ) + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() + + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + #FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = @( + 'Initialize-VISecret', + 'New-VISecret', + 'Get-VISecret', + 'Remove-VISecret', + 'Connect-VIServerWithSecret' + ) + + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + CmdletsToExport = @() + + # Variables to export from this module + VariablesToExport = @() + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + AliasesToExport = @() + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + + } + \ No newline at end of file diff --git a/Modules/VISecret/VMware.VISecret.psm1 b/Modules/VISecret/VMware.VISecret.psm1 new file mode 100644 index 0000000..f93a1b6 --- /dev/null +++ b/Modules/VISecret/VMware.VISecret.psm1 @@ -0,0 +1,314 @@ +<# +.SYNOPSIS +This cmdlet downloads the dependencies and intializes the default settings of the VISecret module + +.PARAMETER Vault +The vault to save the credentials to. The default value is "VMwareSecretStore" + +.DESCRIPTION +This cmdlet downloads the dependecies and initializes the default settings of the VISecret module. +It uses Microsoft.PowerShell.SecretStore as a default vault and sets it in no password mode, so that +the credentials are encrypted, but the user is not prompted for a password. If you want to use a different +vault or to use it with a password you should initialize those settings manually and not use this cmdlet. + +.EXAMPLE +PS C:\> Initialize-VISecret + +Initializes the default settings of the VISecret module +#> +function Initialize-VISecret { + [CmdletBinding()] + param( + [string]$Vault = "VMwareSecretStore" + ) + + process { + Set-SecretStoreConfiguration -Scope CurrentUser -Authentication None -Interaction None -Confirm:$false + + Register-SecretVault -Name $Vault -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault + } +} + +<# +.SYNOPSIS +This cmdlet saves new credential in the secret vault or updates it if it already exists. + +.DESCRIPTION +This cmdlet saves new credential in the secret vault or updates it if it already exists. + +.PARAMETER Server +The IP address or the hostname of the server to save the credential for + +.PARAMETER Password +The password to be saved in the secret vault + +.PARAMETER SecureStringPassword +The SecureString password to be saved in the secret vault + +.PARAMETER User +The username for which to save the credential + +.PARAMETER Vault +The vault to save the credential to. The default value is "VMwareSecretStore" + +.EXAMPLE +PS C:\> New-VISecret -Server 10.10.10.10 -User administrator@vsphere.local -password pass + +Saves the password for the administrator@vsphere.local user on the 10.10.10.10 server in the secret vault + +#> +function New-VISecret { + [CmdletBinding()] + [Alias("Set-VISecret")] + param ( + [Parameter(Mandatory=$true)] + [string]$Server, + [Parameter(Mandatory=$true)] + [string]$User, + [string]$Password, + [securestring]$SecureStringPassword, + [string]$Vault + ) + + begin { + if ([string]::IsNullOrWhiteSpace($password) -and (-not $secureStringPassword)) { + Throw "Either Password or SecureStringPassword parameter needs to be specified" + } + + if (-not [string]::IsNullOrWhiteSpace($password) -and $secureStringPassword) { + Throw "Password and SecureStringPassword parameters cannot be both specified at the same time" + } + } + + process { + $params = @{ + "Name" = "VISecret|"+$server+"|"+$User + } + if ($password) { + $params += @{"Secret" = $password} + } elseif ($secureStringPassword) { + $params += @{"SecureStringSecret" = $secureStringPassword} + } elseif ($Vault) { + $params += @{"Vault" = $Vault} + } + Set-Secret @params + } +} +<# +.SYNOPSIS +Retrieves a credential from the secret store vault. + +.DESCRIPTION +Retrieves a credential from the secret store vault. + +.PARAMETER Server +The IP address or the hostname of the server to retrieve the credential for + +.PARAMETER User +The username for which to retrieve the credential + +.PARAMETER AsPlainText +Specifies that a credential should be returned as a String (in plain text) instead of a SecureString. +To ensure security, you should avoid using plaintext strings whenever possible. + +.PARAMETER Vault +The vault to retrieve the credential from. The default value is "VMwareSecretStore" + +.EXAMPLE +PS C:\> $securePassword = Get-VISecret -Server 10.10.10.10 -User administrator@vsphere.local + +Retrieves the password for the administrator@vsphere.local user on the 10.10.10.10 server from the secret vault +#> +function Get-VISecret { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string]$Server, + [Parameter(Mandatory=$true)] + [string]$User, + [switch]$AsPlainText, + [string]$Vault + ) + + process { + $params = @{ + "Name" = "VISecret|"+$server+"|"+$User + } + if ($AsPlainText.IsPresent) { + $params += @{"AsPlainText" = $AsPlainText.ToBool()} + } elseif ($Vault) { + $params += @{"Vault" = $Vault} + } + Get-Secret @params + } +} + +<# +.SYNOPSIS +Removes a credential from the vault. + +.DESCRIPTION +Removes a credential from the vault. + +.PARAMETER Server +The IP address or the hostname of the server to remove the credential for + +.PARAMETER User +The username for which to remove the credential + +.PARAMETER Vault +The vault to remove the credential from. The default value is "VMwareSecretStore" + +.EXAMPLE +PS C:\> Remove-VISecret -Server 10.10.10.10 -User administrator@vsphere.local + +Removes the password for the administrator@vsphere.local user on the 10.10.10.10 server from the vault +#> +function Remove-VISecret { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string]$Server, + [Parameter(Mandatory=$true)] + [string]$User, + [string]$Vault + ) + + process { + $params = @{ + "Name" = "VISecret|"+$server+"|"+$User + } + if ($Vault) { + $params += @{"Vault" = $Vault} + } + Remove-Secret @params + } +} + +<# +.SYNOPSIS +This cmdlet establishes a connection to a vCenter Server system. + +.DESCRIPTION +This cmdlet establishes a connection to a vCenter Server system. +If a credential object or username and password the cmdlet uses them to connect and if the +-SaveCredential parameter is specified saves them in the vault. If only username +is specified the cmdlet uses the server name and the user name to search for the password in the +vault. + +.PARAMETER Server +Specifies the IP address or the DNS name of the vSphere server to which you want to connect. + +.PARAMETER User +Specifies the user name you want to use for authenticating with the server. + +.PARAMETER Password +Specifies the password you want to use for authenticating with the server. + +.PARAMETER Credential +Specifies a PSCredential object that contains credentials for authenticating with the server. + +.PARAMETER AllLinked +Indicates whether you want to connect to vCenter Server in linked mode. If you specify $true +for the -AllLinked parameter and the server to which you want to connect is a part of a federation +vCenter Server, you'll be connected to all members of the linked vCenter Server. To use this +option, PowerCLI must be configured to work in multiple servers connection mode. To configure +PowerCLI to support multiple servers connection, specify Multiple for the DefaultVIServerMode +parameter of the Set-PowerCLIConfiguration cmdlet. + +.PARAMETER Force +Suppresses all user interface prompts during the cmdlet execution. + +.PARAMETER NotDefault +Indicates that you do not want to include the server to which you connect into the $defaultVIServers variable. + +.PARAMETER Port +Specifies the port on the server you want to use for the connection. + +.PARAMETER Protocol +Specifies the Internet protocol you want to use for the connection. It can be either http or https. + +.PARAMETER SaveCredentials +Indicates that you want to save the specified credentials in the vault. + +.PARAMETER Vault +The vault to save the credential to. The default value is "VMwareSecretStore" + +.EXAMPLE +Connect-VIServer -Server 10.10.10.10 -User administrator@vsphere.local + +Connects to a vSphere server using the saved credential for the specified user + +.EXAMPLE +Connect-VIServer -Server 10.10.10.10 -User administrator@vsphere.local -Password pass -SaveCredential + +Connects to a vSphere server using the specified username and password and saves them in the vault +#> +function Connect-VIServerWithSecret { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string]$Server, + [string]$User, + [string]$Password, + [pscredential]$Credential, + [switch]$AllLinked, + [switch]$Force, + [switch]$NotDefault, + [int]$Port, + [string]$Protocol, + [switch]$SaveCredentials, + [string]$Vault + ) + + begin { + if ([string]::IsNullOrWhiteSpace($User) -and (-not $Credential)) { + if ($global:defaultUser) { + $User = $global:defaultUser + } else { + Throw "Either User or Credential parameters needs to be specified" + } + } + + if ((-not [string]::IsNullOrWhiteSpace($User) -or -not [string]::IsNullOrWhiteSpace($Password)) -and $Credential) { + Throw "User/Password and Credential parameters cannot be both specified at the same time" + } + } + + process { + $params = @{ + "Server" = $Server + "AllLinked" = $AllLinked + "Force" = $Force + "NotDefault" = $NotDefault + } + if ($Protocol) { + $params += @{"Protocol" = $Protocol} + } + if ($Port) { + $params += @{"Port" = $Port} + } + if ($User) { + if (-not $Password) { + if ($Vault) { + $secret = Get-Secret -Name ("VISecret|"+$server+"|"+$User) -Vault $Vault -ErrorAction SilentlyContinue + } else { + $secret = Get-Secret -Name ("VISecret|"+$server+"|"+$User) -ErrorAction SilentlyContinue + } + if (-not $secret) { + Throw "No password has been found for this server and user in the password vault" + } + $Credential = New-Object System.Management.Automation.PSCredential ($User, $secret) + } + else { + $securePass = ConvertTo-SecureString -String $Password -AsPlainText + $Credential = New-Object System.Management.Automation.PSCredential ($User, $securePass) + } + } + $params += @{"Credential" = $Credential} + Connect-VIServer @params + if ($SaveCredentials) { + New-VISecret -Server $Server -User $User -SecureStringPassword $Credential.Password -Vault $Vault + } + } +} \ No newline at end of file