Skip to content

Commit

Permalink
Use sessions (#3496)
Browse files Browse the repository at this point in the history
Add PowerShell configurations and PSRemoting when creating containers
Allow standard Container sessions (when host is running PS5 in admin
mode) to be to PS5 or PS7 (base on version and usePwshForBC24 flag)
Use WinRm to create a session to a container when running PS7 or
non-admin mode.
WinRm session uses HTTPS unless $bccontainerHelperConfig.useSslForWinRm
is set to $false
Using HTTP for WinRm requires you to add trustedHosts to the hosts winrm
configuration (if not running as administrator)

---------

Co-authored-by: freddydk <[email protected]>
Co-authored-by: Alexander Holstrup <[email protected]>
  • Loading branch information
3 people committed Apr 22, 2024
1 parent f157a40 commit f905714
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 43 deletions.
4 changes: 3 additions & 1 deletion BC.HelperFunctions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ function Get-ContainerHelperConfig {
"genericImageNameFilesOnly" = 'mcr.microsoft.com/businesscentral:{1}-filesonly'
"usePsSession" = $true
"usePwshForBc24" = $true
"tryWinRmSession" = !$isAdministrator
"useSslForWinRmSession" = $true
"tryWinRmSession" = $isPsCore -or !$isAdministrator
"alwaysUseWinRmSession" = $false
"addTryCatchToScriptBlock" = $true
"killPsSessionProcess" = $false
"useVolumes" = $false
Expand Down
2 changes: 1 addition & 1 deletion ContainerHandling/Enter-NavContainer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function Enter-BcContainer {

Process {
if ($bcContainerHelperConfig.usePsSession) {
$session = Get-BcContainerSession -containerName $containerName -silent -tryWinRmSession
$session = Get-BcContainerSession -containerName $containerName -silent
Enter-PSSession -Session $session
if ($session.ComputerType -eq 'Container') {
Invoke-Command -Session $session -ScriptBlock {
Expand Down
40 changes: 24 additions & 16 deletions ContainerHandling/Get-NavContainerSession.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ function Get-BcContainerSession {
Param (
[string] $containerName = $bcContainerHelperConfig.defaultContainerName,
[switch] $tryWinRmSession = $bccontainerHelperConfig.tryWinRmSession,
[switch] $alwaysUseWinRmSession = $bccontainerHelperConfig.alwaysUseWinRmSession,
[switch] $usePwsh = $bccontainerHelperConfig.usePwshForBc24,
[switch] $silent,
[switch] $reinit
)
Expand All @@ -37,34 +39,40 @@ function Get-BcContainerSession {
}
}
if (!$session) {
[System.Version]$platformVersion = Get-BcContainerPlatformVersion -containerOrImageName $containerName
if ($platformVersion -lt [System.Version]"24.0.0.0") {
$usePwsh = $false
}
$configurationName = 'Microsoft.PowerShell'
if ($usePwsh) {
$configurationName = 'PowerShell.7'
}
if ($isInsideContainer) {
$session = New-PSSession -Credential $bcContainerHelperConfig.WinRmCredentials -ComputerName $containerName -Authentication Basic -UseSSL -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck)
}
elseif ($isAdministrator) {
elseif ($isAdministrator -and !$bcContainerHelperConfig.alwaysUseWinRmSession) {
try {
$containerId = Get-BcContainerId -containerName $containerName
$session = New-PSSession -ContainerId $containerId -RunAsAdministrator -ErrorAction SilentlyContinue
$session = New-PSSession -ContainerId $containerId -RunAsAdministrator -ErrorAction SilentlyContinue -ConfigurationName $configurationName
}
catch {}
}
if (!$session) {
if (!$tryWinRmSession) {
throw "Unable to create a session for container $containerName (tryWinRmSession is false)"
if (!($alwaysUseWinRmSession -or $tryWinRmSession)) {
throw "Unable to create session for container $containerName (alwaysUseWinRmSession and tryWinRmSession are both false)"

}
$useSSL = $bcContainerHelperConfig.useSslForWinRmSession
$UUID = (Get-CimInstance win32_ComputerSystemProduct).UUID
$credential = New-Object PSCredential -ArgumentList 'winrm', (ConvertTo-SecureString -string $UUID -AsPlainText -force)
Invoke-ScriptInBcContainer -containerName $containerName -useSession:$false -scriptblock { Param([PSCredential] $credential)
$winrmuser = get-localuser -name $credential.UserName -ErrorAction SilentlyContinue
if (!$winrmuser) {
$cert = New-SelfSignedCertificate -DnsName "dontcare" -CertStoreLocation Cert:\LocalMachine\My
winrm create winrm/config/Listener?Address=*+Transport=HTTPS ('@{Hostname="dontcare"; CertificateThumbprint="' + $cert.Thumbprint + '"}') | Out-Null
winrm set winrm/config/service/Auth '@{Basic="true"}' | Out-Null
Write-Host "`nCreating Container user $($credential.UserName)"
New-LocalUser -AccountNeverExpires -PasswordNeverExpires -FullName $credential.UserName -Name $credential.UserName -Password $credential.Password | Out-Null
Add-LocalGroupMember -Group administrators -Member $credential.UserName | Out-Null
}
} -argumentList $credential
$session = New-PSSession -Credential $credential -ComputerName $containerName -Authentication Basic -useSSL -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck)
if ($useSSL) {
$sessionOption = New-PSSessionOption -Culture 'en-US' -UICulture 'en-US' -SkipCACheck -SkipCNCheck
$Session = New-PSSession -ConnectionUri "https://$($containerName):5986" -Credential $credential -Authentication Basic -SessionOption $sessionOption -ConfigurationName $configurationName
}
else {
$sessionOption = New-PSSessionOption -Culture 'en-US' -UICulture 'en-US'
$Session = New-PSSession -ConnectionUri "http://$($containerName):5985" -Credential $credential -Authentication Basic -SessionOption $sessionOption -ConfigurationName $configurationName
}
}
$newsession = $true
}
Expand Down
38 changes: 13 additions & 25 deletions ContainerHandling/Invoke-ScriptInNavContainer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,20 @@ function Invoke-ScriptInBcContainer {
)

$file = Join-Path $bcContainerHelperConfig.hostHelperFolder ([GUID]::NewGuid().Tostring()+'.ps1')
$containerFile = ""
$shell = 'powershell'
if ($usePwsh) {
[System.Version]$platformVersion = Get-BcContainerPlatformVersion -containerOrImageName $containerName
if ($platformVersion -ge [System.Version]"24.0.0.0") {
$useSession = $false
$shell = 'pwsh'
}
else {
$usePwsh = $false
}
}
if (-not $usePwsh) {
if ($isInsideContainer) {
$useSession = $true
}
else {
$containerFile = Get-BcContainerPath -containerName $containerName -path $file
if ("$containerFile" -eq "") {
$useSession = $true
}
}
$containerFile = $containerFile = Get-BcContainerPath -containerName $containerName -path $file
if ($isInsideContainer -or "$containerFile" -eq "") {
$useSession = $true
}

if ($useSession) {
try {
$session = Get-BcContainerSession -containerName $containerName -silent
$session = Get-BcContainerSession -containerName $containerName -silent -usePwsh:$usePwsh
}
catch {
if ($isInsideContainer) {
Write-Host "Error trying to establish session, retrying in 5 seconds"
Start-Sleep -Seconds 5
$session = Get-BcContainerSession -containerName $containerName -silent
$session = Get-BcContainerSession -containerName $containerName -silent -usePwsh:$usePwsh
}
else {
$useSession = $false
Expand Down Expand Up @@ -129,7 +110,14 @@ function Invoke-ScriptInBcContainer {
}
} else {
if ("$containerFile" -eq "") {
$containerFile = Get-BcContainerPath -containerName $containerName -path $file -throw
throw "$($bcContainerHelperConfig.hostHelperFolder) is not shared with the container, cannot invoke scripts in container without using a session"
}
$shell = 'powershell'
if ($usePwsh) {
[System.Version]$platformVersion = Get-BcContainerPlatformVersion -containerOrImageName $containerName
if ($platformVersion -ge [System.Version]"24.0.0.0") {
$shell = 'pwsh'
}
}
$hostOutputFile = "$file.output"
$containerOutputFile = "$containerFile.output"
Expand Down
67 changes: 67 additions & 0 deletions ContainerHandling/New-NavContainer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1597,8 +1597,75 @@ if (!$restartingInstance) {
Add-LocalGroupMember -Group administrators -Member '+$bcContainerHelperConfig.WinRmCredentials.UserName+'
}
') | Add-Content -Path "$myfolder\AdditionalSetup.ps1"
}
else {
$UUID = (Get-CimInstance win32_ComputerSystemProduct).UUID
('
if (!$restartingInstance) {
Write-Host "Enable PSRemoting and setup user for winrm"
Enable-PSRemoting | Out-Null
Get-PSSessionConfiguration | Out-null
pwsh.exe -Command "Enable-PSRemoting -WarningAction SilentlyContinue | Out-Null; Get-PSSessionConfiguration | Out-Null"
$credential = New-Object PSCredential -ArgumentList "winrm", (ConvertTo-SecureString -string "'+$UUID+'" -AsPlainText -force)
New-LocalUser -AccountNeverExpires -PasswordNeverExpires -FullName $credential.UserName -Name $credential.UserName -Password $credential.Password | Out-Null
Add-LocalGroupMember -Group administrators -Member $credential.UserName | Out-Null
winrm set winrm/config/service/Auth ''@{Basic="true"}'' | Out-Null
}
') | Add-Content -Path "$myfolder\AdditionalSetup.ps1"
if ($bccontainerHelperConfig.useSslForWinRmSession) {
$additionalParameters += @("--expose 5986")
('
if (!$restartingInstance) {
Write-Host "Creating self-signed certificate for winrm"
$cert = New-SelfSignedCertificate -CertStoreLocation cert:\localmachine\my -DnsName $env:computername -NotBefore (get-date).AddDays(-1) -NotAfter (get-date).AddYears(5) -Provider "Microsoft RSA SChannel Cryptographic Provider" -KeyLength 2048
winrm create winrm/config/Listener?Address=*+Transport=HTTPS ("@{Hostname=""$env:computername""; CertificateThumbprint=""$($cert.Thumbprint)""}") | Out-Null
}
') | Add-Content -Path "$myfolder\AdditionalSetup.ps1"
}
else {
$additionalParameters += @("--expose 5985")
('
if (!$restartingInstance) {
Write-Host "Allow unencrypted communication to container"
winrm set winrm/config/service ''@{AllowUnencrypted="true"}'' | Out-Null
}
') | Add-Content -Path "$myfolder\AdditionalSetup.ps1"
}

if (-not $bccontainerHelperConfig.useSslForWinRmSession) {
try {
[xml]$conf = winrm get winrm/config/client -format:pretty
$trustedHosts = @($conf.Client.TrustedHosts.Split(','))
if (-not $trustedHosts) {
$trustedHosts = @()
}
$isTrusted = $trustedHosts | Where-Object { $containerName -like $_ }
if (!($isTrusted)) {
if (!$isAdministrator) {
Write-Host "$containerName is not a trusted host. You need to get an administrator to add $containerName to the trusted winrm hosts on your machine"
}
else {
Write-Host "Adding $containerName to trusted hosts ($($trustedHosts -join ','))"
$trustedHosts += $containerName
winrm set winrm/config/client "@{TrustedHosts=""$($trustedHosts -join ',')""}" | Out-Null
}
}
if ($conf.Client.AllowUnencrypted -eq 'false') {
if (!$isAdministrator) {
Write-Host "Unencrypted communication is not allowed. You need to get an administrator to allow unencrypted communication"
}
else {
Write-Host "Allow unencrypted communication"
winrm set winrm/config/client '@{AllowUnencrypted="true"}' | Out-Null
}
}
}
catch {
Write-Host "Unexpected error when checking winrm configuration, you might not be able to connect to the container using winrm unencrypted"
}
}
}

if ($includeCSide) {
$programFilesFolder = Join-Path $containerFolder "Program Files"
New-Item -Path $programFilesFolder -ItemType Directory -ErrorAction Ignore | Out-Null
Expand Down
12 changes: 12 additions & 0 deletions ContainerHandling/Remove-NavContainer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ try {
. (Join-Path $PSScriptRoot "updatehosts.ps1") -hostsFile "c:\windows\system32\drivers\etc\hosts" -theHostname $tenantHostname -theIpAddress ""
}

if ($isAdministrator) {
try {
[xml]$conf = winrm get winrm/config/client -format:pretty
$trustedHosts = $conf.Client.TrustedHosts.Split(',')
if ($trustedHosts -contains $containerName) {
Write-Host "Removing $containerName from trusted hosts ($($trustedHosts -join ','))"
winrm set winrm/config/client "@{TrustedHosts=""$(@($trustedHosts | Where-Object { $_ -ne $containerName }) -join ',')""}" | Out-Null
}
}
catch {}
}

if ($myVolume) {
Write-Host "Removing volume $myVolumeName"
docker volume remove $myVolumeName
Expand Down

0 comments on commit f905714

Please sign in to comment.