diff --git a/d365fo.tools/d365fo.tools.psd1 b/d365fo.tools/d365fo.tools.psd1 index 8f7981cd..b138df48 100644 --- a/d365fo.tools/d365fo.tools.psd1 +++ b/d365fo.tools/d365fo.tools.psd1 @@ -168,6 +168,7 @@ 'Get-D365TfsUri', 'Get-D365TfsWorkspace', + 'Get-D365UdeDatabaseCredential', 'Get-D365Url', 'Get-D365User', 'Get-D365UserAuthenticationDetail', @@ -310,6 +311,8 @@ 'Set-D365SqlPackagePath', 'Set-D365SysAdmin', + 'Set-D365UdeDatabaseCredential', + 'Set-D365WebConfigDatabase', 'Set-D365WebServerType', @@ -323,6 +326,8 @@ 'Start-D365EnvironmentV2', 'Start-D365EventTrace', + 'Start-D365UdeSsmsSession', + 'Stop-D365Environment', 'Stop-D365EventTrace', diff --git a/d365fo.tools/functions/get-d365udedatabasecredential.ps1 b/d365fo.tools/functions/get-d365udedatabasecredential.ps1 new file mode 100644 index 00000000..84dd85f2 --- /dev/null +++ b/d365fo.tools/functions/get-d365udedatabasecredential.ps1 @@ -0,0 +1,43 @@ +function Get-D365UdeDatabaseCredential { + [CmdletBinding()] + param ( + [Alias("Name")] + [string] $Id = "*", + + [switch] $ShowPassword + ) + + begin { + if ($null -eq (Get-Module TUN.CredentialManager -ListAvailable)) { + Write-PSFMessage -Level Host -Message "This cmdlet needs the TUN.CredentialManager module. Please install it from the PowerShell Gallery with Install-Module -Name TUN.CredentialManager and try again." + Stop-PSFFunction -Message "Stopping because the TUN.CredentialManager module is not available." + + return + } + + if (Test-PSFFunctionInterrupt) { return } + + Import-Module TUN.CredentialManager + } + + process { + if (Test-PSFFunctionInterrupt) { return } + + $credentials = [hashtable](Get-PSFConfigValue -FullName "d365fo.tools.ude.credentials") + + $col = @( + foreach ($key in $credentials.Keys) { + if ($key -like $Id) { + $credentials[$key] + } + } + ) + + if ($ShowPassword) { + $col + } + else { + $col | Select-PSFObject -Property * -ExcludeProperty Password + } + } +} \ No newline at end of file diff --git a/d365fo.tools/functions/set-d365udedatabasecredential.ps1 b/d365fo.tools/functions/set-d365udedatabasecredential.ps1 new file mode 100644 index 00000000..049262db --- /dev/null +++ b/d365fo.tools/functions/set-d365udedatabasecredential.ps1 @@ -0,0 +1,75 @@ + +function Set-D365UdeDatabaseCredential { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] $Id, + + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] + [Alias("DatabaseServer")] + [Alias("ServerName")] + [string] $Server, + + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] + [Alias("DatabaseName")] + [string] $Database, + + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] + [Alias("SqlUser")] + [string] $Username, + + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] + [Alias("SqlPwd")] + [string] $Password, + + [Alias("SQLJITExpirationTime")] + [datetime] $ValidUntil = (Get-Date).AddHours(8) + ) + + begin { + if ($null -eq (Get-Module TUN.CredentialManager -ListAvailable)) { + Write-PSFMessage -Level Host -Message "This cmdlet needs the TUN.CredentialManager module. Please install it from the PowerShell Gallery with Install-Module -Name TUN.CredentialManager and try again." + Stop-PSFFunction -Message "Stopping because the TUN.CredentialManager module is not available." + + return + } + + if (Test-PSFFunctionInterrupt) { return } + + Import-Module TUN.CredentialManager + } + + process { + if (Test-PSFFunctionInterrupt) { return } + + $SqlServerGUID = "8c91a03d-f9b4-46c0-a305-b5dcc79ff907" + + $details = [PSCustomObject][ordered]@{ + Id = $Id + Server = $($Server) + Database = $($Database) + Username = $($Username) + Password = $($Password) + Expiration = $($ValidUntil.ToString("s")) + } + + # Setting up the SQL Server Management Studio (SSMS) Credential for version 20 - 21 + 20, 21 | ForEach-Object { + New-StoredCredential ` + -UserName $Username ` + -Password $Password ` + -Persist LocalMachine ` + -Target "Microsoft:SSMS:$($_):$($Server):$($Username):$($SqlServerGUID):1" > $null + } + + $credentials = [hashtable](Get-PSFConfigValue -FullName "d365fo.tools.ude.credentials") + $credentials."$Id" = $details + + Set-PSFConfig -FullName "d365fo.tools.ude.credentials" -Value $credentials + Register-PSFConfig -FullName "d365fo.tools.ude.credentials" -Scope UserDefault + + Get-D365UdeDatabaseCredential -Id $Id + } +} \ No newline at end of file diff --git a/d365fo.tools/functions/start-d365udessmssession.ps1 b/d365fo.tools/functions/start-d365udessmssession.ps1 new file mode 100644 index 00000000..480b0b65 --- /dev/null +++ b/d365fo.tools/functions/start-d365udessmssession.ps1 @@ -0,0 +1,41 @@ + +function Start-D365UdeSsmsSession { + param ( + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] + [string] $Id, + + [ValidateSet(20, 21)] + [int] $Version = 20 + ) + + process { + $udeCreds = Get-D365UdeDatabaseCredential -Id $Id + + if ($null -eq $udeCreds) { + Write-PSFMessage -Level Host -Message "No credential found for Id '$Id'. Please check the Id and try again." + Stop-PSFFunction -Message "Stopping because no matching credential was found." + + return + } + + # Hack to get the SSMS executable path from the registry + $ssmsInstalled = Get-ChildItem ` + -Path Registry::HKEY_CLASSES_ROOT\ssms.*\shell\Open\Command | ` + Select-Object -ExpandProperty PsPath | ` + ForEach-Object { (Get-ItemProperty -Path $_)."(Default)" } | ` + Select-String -Pattern '^[\"]?(.*ssms\.exe)["]?\s*"%1"' | ` + ForEach-Object { $_.Matches.Groups[1].Value } | Select-Object -Unique + + $executablePath = $ssmsInstalled | ` + Where-Object { $_ -match "Microsoft SQL Server Management Studio $($Version)\b" } | ` + Select-Object -First 1 + + if ([string]::IsNullOrWhiteSpace($executablePath)) { + Write-PSFMessage -Level Host -Message "Could not find a valid SSMS executable for version $Version. Please ensure the version is installed or try a different version." + Stop-PSFFunction -Message "Stopping because SSMS executable was not found." + return + } + + & $executablePath -S $($udeCreds.Server) -d $($udeCreds.Database) -U $($udeCreds.Username) + } +} \ No newline at end of file diff --git a/d365fo.tools/internal/configurations/configuration.ps1 b/d365fo.tools/internal/configurations/configuration.ps1 index 40fc2dd8..c0522b64 100644 --- a/d365fo.tools/internal/configurations/configuration.ps1 +++ b/d365fo.tools/internal/configurations/configuration.ps1 @@ -40,3 +40,5 @@ Set-PSFConfig -FullName "d365fo.tools.path.rsatplayback" -Value "C:\Users\$($env Set-PSFConfig -FullName "d365fo.tools.path.azcopy" -Value "C:\temp\d365fo.tools\AzCopy\AzCopy.exe" -Initialize -Description "Path to the default location where AzCopy.exe is located." Set-PSFConfig -FullName "d365fo.tools.path.nuget" -Value "C:\temp\d365fo.tools\nuget\nuget.exe" -Initialize -Description "Path to the default location where nuget.exe is located." + +Set-PSFConfig -FullName "d365fo.tools.ude.credentials" -Value @{} -Initialize -Description "Object that stores different Ude Database credentials and their details." diff --git a/d365fo.tools/internal/tepp/assignment.ps1 b/d365fo.tools/internal/tepp/assignment.ps1 index 6b7f4237..29acdd4c 100644 --- a/d365fo.tools/internal/tepp/assignment.ps1 +++ b/d365fo.tools/internal/tepp/assignment.ps1 @@ -34,3 +34,8 @@ Register-PSFTeppArgumentCompleter -Command Add-D365BroadcastMessageConfig -Param #Event Trace Register-PSFTeppArgumentCompleter -Command Start-D365EventTrace -Parameter ProviderName -Name d365fo.tools.event.trace.providers Register-PSFTeppArgumentCompleter -Command Start-D365EventTrace -Parameter OutputFormat -Name d365fo.tools.event.trace.format.options + +#UDE Credentials +Register-PSFTeppArgumentCompleter -Command Get-D365UdeDatabaseCredential -Parameter Id -Name "d365fo.tools.ude.credentials" +Register-PSFTeppArgumentCompleter -Command Start-D365UdeSsmsSession -Parameter Id -Name "d365fo.tools.ude.credentials" +Register-PSFTeppArgumentCompleter -Command Set-D365UdeDatabaseCredential -Parameter Id -Name "d365fo.tools.ude.credentials" diff --git a/d365fo.tools/internal/tepp/configurations.tepp.ps1 b/d365fo.tools/internal/tepp/configurations.tepp.ps1 new file mode 100644 index 00000000..e1d383c5 --- /dev/null +++ b/d365fo.tools/internal/tepp/configurations.tepp.ps1 @@ -0,0 +1,3 @@ +$scriptBlock = { Get-D365UdeDatabaseCredential | Sort-Object Id | Select-Object -ExpandProperty Id } + +Register-PSFTeppScriptblock -Name "d365fo.tools.ude.credentials" -ScriptBlock $scriptBlock -Mode Simple