Skip to content

Commit f905714

Browse files
freddydkaholstrup1
andauthored
Use sessions (#3496)
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]>
1 parent f157a40 commit f905714

6 files changed

+120
-43
lines changed

BC.HelperFunctions.ps1

+3-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ function Get-ContainerHelperConfig {
1515
"genericImageNameFilesOnly" = 'mcr.microsoft.com/businesscentral:{1}-filesonly'
1616
"usePsSession" = $true
1717
"usePwshForBc24" = $true
18-
"tryWinRmSession" = !$isAdministrator
18+
"useSslForWinRmSession" = $true
19+
"tryWinRmSession" = $isPsCore -or !$isAdministrator
20+
"alwaysUseWinRmSession" = $false
1921
"addTryCatchToScriptBlock" = $true
2022
"killPsSessionProcess" = $false
2123
"useVolumes" = $false

ContainerHandling/Enter-NavContainer.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function Enter-BcContainer {
1919

2020
Process {
2121
if ($bcContainerHelperConfig.usePsSession) {
22-
$session = Get-BcContainerSession -containerName $containerName -silent -tryWinRmSession
22+
$session = Get-BcContainerSession -containerName $containerName -silent
2323
Enter-PSSession -Session $session
2424
if ($session.ComputerType -eq 'Container') {
2525
Invoke-Command -Session $session -ScriptBlock {

ContainerHandling/Get-NavContainerSession.ps1

+24-16
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ function Get-BcContainerSession {
1717
Param (
1818
[string] $containerName = $bcContainerHelperConfig.defaultContainerName,
1919
[switch] $tryWinRmSession = $bccontainerHelperConfig.tryWinRmSession,
20+
[switch] $alwaysUseWinRmSession = $bccontainerHelperConfig.alwaysUseWinRmSession,
21+
[switch] $usePwsh = $bccontainerHelperConfig.usePwshForBc24,
2022
[switch] $silent,
2123
[switch] $reinit
2224
)
@@ -37,34 +39,40 @@ function Get-BcContainerSession {
3739
}
3840
}
3941
if (!$session) {
42+
[System.Version]$platformVersion = Get-BcContainerPlatformVersion -containerOrImageName $containerName
43+
if ($platformVersion -lt [System.Version]"24.0.0.0") {
44+
$usePwsh = $false
45+
}
46+
$configurationName = 'Microsoft.PowerShell'
47+
if ($usePwsh) {
48+
$configurationName = 'PowerShell.7'
49+
}
4050
if ($isInsideContainer) {
4151
$session = New-PSSession -Credential $bcContainerHelperConfig.WinRmCredentials -ComputerName $containerName -Authentication Basic -UseSSL -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck)
4252
}
43-
elseif ($isAdministrator) {
53+
elseif ($isAdministrator -and !$bcContainerHelperConfig.alwaysUseWinRmSession) {
4454
try {
4555
$containerId = Get-BcContainerId -containerName $containerName
46-
$session = New-PSSession -ContainerId $containerId -RunAsAdministrator -ErrorAction SilentlyContinue
56+
$session = New-PSSession -ContainerId $containerId -RunAsAdministrator -ErrorAction SilentlyContinue -ConfigurationName $configurationName
4757
}
4858
catch {}
4959
}
5060
if (!$session) {
51-
if (!$tryWinRmSession) {
52-
throw "Unable to create a session for container $containerName (tryWinRmSession is false)"
61+
if (!($alwaysUseWinRmSession -or $tryWinRmSession)) {
62+
throw "Unable to create session for container $containerName (alwaysUseWinRmSession and tryWinRmSession are both false)"
63+
5364
}
65+
$useSSL = $bcContainerHelperConfig.useSslForWinRmSession
5466
$UUID = (Get-CimInstance win32_ComputerSystemProduct).UUID
5567
$credential = New-Object PSCredential -ArgumentList 'winrm', (ConvertTo-SecureString -string $UUID -AsPlainText -force)
56-
Invoke-ScriptInBcContainer -containerName $containerName -useSession:$false -scriptblock { Param([PSCredential] $credential)
57-
$winrmuser = get-localuser -name $credential.UserName -ErrorAction SilentlyContinue
58-
if (!$winrmuser) {
59-
$cert = New-SelfSignedCertificate -DnsName "dontcare" -CertStoreLocation Cert:\LocalMachine\My
60-
winrm create winrm/config/Listener?Address=*+Transport=HTTPS ('@{Hostname="dontcare"; CertificateThumbprint="' + $cert.Thumbprint + '"}') | Out-Null
61-
winrm set winrm/config/service/Auth '@{Basic="true"}' | Out-Null
62-
Write-Host "`nCreating Container user $($credential.UserName)"
63-
New-LocalUser -AccountNeverExpires -PasswordNeverExpires -FullName $credential.UserName -Name $credential.UserName -Password $credential.Password | Out-Null
64-
Add-LocalGroupMember -Group administrators -Member $credential.UserName | Out-Null
65-
}
66-
} -argumentList $credential
67-
$session = New-PSSession -Credential $credential -ComputerName $containerName -Authentication Basic -useSSL -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck)
68+
if ($useSSL) {
69+
$sessionOption = New-PSSessionOption -Culture 'en-US' -UICulture 'en-US' -SkipCACheck -SkipCNCheck
70+
$Session = New-PSSession -ConnectionUri "https://$($containerName):5986" -Credential $credential -Authentication Basic -SessionOption $sessionOption -ConfigurationName $configurationName
71+
}
72+
else {
73+
$sessionOption = New-PSSessionOption -Culture 'en-US' -UICulture 'en-US'
74+
$Session = New-PSSession -ConnectionUri "http://$($containerName):5985" -Credential $credential -Authentication Basic -SessionOption $sessionOption -ConfigurationName $configurationName
75+
}
6876
}
6977
$newsession = $true
7078
}

ContainerHandling/Invoke-ScriptInNavContainer.ps1

+13-25
Original file line numberDiff line numberDiff line change
@@ -31,39 +31,20 @@ function Invoke-ScriptInBcContainer {
3131
)
3232

3333
$file = Join-Path $bcContainerHelperConfig.hostHelperFolder ([GUID]::NewGuid().Tostring()+'.ps1')
34-
$containerFile = ""
35-
$shell = 'powershell'
36-
if ($usePwsh) {
37-
[System.Version]$platformVersion = Get-BcContainerPlatformVersion -containerOrImageName $containerName
38-
if ($platformVersion -ge [System.Version]"24.0.0.0") {
39-
$useSession = $false
40-
$shell = 'pwsh'
41-
}
42-
else {
43-
$usePwsh = $false
44-
}
45-
}
46-
if (-not $usePwsh) {
47-
if ($isInsideContainer) {
48-
$useSession = $true
49-
}
50-
else {
51-
$containerFile = Get-BcContainerPath -containerName $containerName -path $file
52-
if ("$containerFile" -eq "") {
53-
$useSession = $true
54-
}
55-
}
34+
$containerFile = $containerFile = Get-BcContainerPath -containerName $containerName -path $file
35+
if ($isInsideContainer -or "$containerFile" -eq "") {
36+
$useSession = $true
5637
}
5738

5839
if ($useSession) {
5940
try {
60-
$session = Get-BcContainerSession -containerName $containerName -silent
41+
$session = Get-BcContainerSession -containerName $containerName -silent -usePwsh:$usePwsh
6142
}
6243
catch {
6344
if ($isInsideContainer) {
6445
Write-Host "Error trying to establish session, retrying in 5 seconds"
6546
Start-Sleep -Seconds 5
66-
$session = Get-BcContainerSession -containerName $containerName -silent
47+
$session = Get-BcContainerSession -containerName $containerName -silent -usePwsh:$usePwsh
6748
}
6849
else {
6950
$useSession = $false
@@ -129,7 +110,14 @@ function Invoke-ScriptInBcContainer {
129110
}
130111
} else {
131112
if ("$containerFile" -eq "") {
132-
$containerFile = Get-BcContainerPath -containerName $containerName -path $file -throw
113+
throw "$($bcContainerHelperConfig.hostHelperFolder) is not shared with the container, cannot invoke scripts in container without using a session"
114+
}
115+
$shell = 'powershell'
116+
if ($usePwsh) {
117+
[System.Version]$platformVersion = Get-BcContainerPlatformVersion -containerOrImageName $containerName
118+
if ($platformVersion -ge [System.Version]"24.0.0.0") {
119+
$shell = 'pwsh'
120+
}
133121
}
134122
$hostOutputFile = "$file.output"
135123
$containerOutputFile = "$containerFile.output"

ContainerHandling/New-NavContainer.ps1

+67
Original file line numberDiff line numberDiff line change
@@ -1597,8 +1597,75 @@ if (!$restartingInstance) {
15971597
Add-LocalGroupMember -Group administrators -Member '+$bcContainerHelperConfig.WinRmCredentials.UserName+'
15981598
}
15991599
') | Add-Content -Path "$myfolder\AdditionalSetup.ps1"
1600+
}
1601+
else {
1602+
$UUID = (Get-CimInstance win32_ComputerSystemProduct).UUID
1603+
('
1604+
if (!$restartingInstance) {
1605+
Write-Host "Enable PSRemoting and setup user for winrm"
1606+
Enable-PSRemoting | Out-Null
1607+
Get-PSSessionConfiguration | Out-null
1608+
pwsh.exe -Command "Enable-PSRemoting -WarningAction SilentlyContinue | Out-Null; Get-PSSessionConfiguration | Out-Null"
1609+
$credential = New-Object PSCredential -ArgumentList "winrm", (ConvertTo-SecureString -string "'+$UUID+'" -AsPlainText -force)
1610+
New-LocalUser -AccountNeverExpires -PasswordNeverExpires -FullName $credential.UserName -Name $credential.UserName -Password $credential.Password | Out-Null
1611+
Add-LocalGroupMember -Group administrators -Member $credential.UserName | Out-Null
1612+
winrm set winrm/config/service/Auth ''@{Basic="true"}'' | Out-Null
1613+
}
1614+
') | Add-Content -Path "$myfolder\AdditionalSetup.ps1"
1615+
if ($bccontainerHelperConfig.useSslForWinRmSession) {
1616+
$additionalParameters += @("--expose 5986")
1617+
('
1618+
if (!$restartingInstance) {
1619+
Write-Host "Creating self-signed certificate for winrm"
1620+
$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
1621+
winrm create winrm/config/Listener?Address=*+Transport=HTTPS ("@{Hostname=""$env:computername""; CertificateThumbprint=""$($cert.Thumbprint)""}") | Out-Null
1622+
}
1623+
') | Add-Content -Path "$myfolder\AdditionalSetup.ps1"
1624+
}
1625+
else {
1626+
$additionalParameters += @("--expose 5985")
1627+
('
1628+
if (!$restartingInstance) {
1629+
Write-Host "Allow unencrypted communication to container"
1630+
winrm set winrm/config/service ''@{AllowUnencrypted="true"}'' | Out-Null
1631+
}
1632+
') | Add-Content -Path "$myfolder\AdditionalSetup.ps1"
1633+
}
16001634

1635+
if (-not $bccontainerHelperConfig.useSslForWinRmSession) {
1636+
try {
1637+
[xml]$conf = winrm get winrm/config/client -format:pretty
1638+
$trustedHosts = @($conf.Client.TrustedHosts.Split(','))
1639+
if (-not $trustedHosts) {
1640+
$trustedHosts = @()
1641+
}
1642+
$isTrusted = $trustedHosts | Where-Object { $containerName -like $_ }
1643+
if (!($isTrusted)) {
1644+
if (!$isAdministrator) {
1645+
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"
1646+
}
1647+
else {
1648+
Write-Host "Adding $containerName to trusted hosts ($($trustedHosts -join ','))"
1649+
$trustedHosts += $containerName
1650+
winrm set winrm/config/client "@{TrustedHosts=""$($trustedHosts -join ',')""}" | Out-Null
1651+
}
1652+
}
1653+
if ($conf.Client.AllowUnencrypted -eq 'false') {
1654+
if (!$isAdministrator) {
1655+
Write-Host "Unencrypted communication is not allowed. You need to get an administrator to allow unencrypted communication"
1656+
}
1657+
else {
1658+
Write-Host "Allow unencrypted communication"
1659+
winrm set winrm/config/client '@{AllowUnencrypted="true"}' | Out-Null
1660+
}
1661+
}
1662+
}
1663+
catch {
1664+
Write-Host "Unexpected error when checking winrm configuration, you might not be able to connect to the container using winrm unencrypted"
1665+
}
1666+
}
16011667
}
1668+
16021669
if ($includeCSide) {
16031670
$programFilesFolder = Join-Path $containerFolder "Program Files"
16041671
New-Item -Path $programFilesFolder -ItemType Directory -ErrorAction Ignore | Out-Null

ContainerHandling/Remove-NavContainer.ps1

+12
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ try {
6262
. (Join-Path $PSScriptRoot "updatehosts.ps1") -hostsFile "c:\windows\system32\drivers\etc\hosts" -theHostname $tenantHostname -theIpAddress ""
6363
}
6464

65+
if ($isAdministrator) {
66+
try {
67+
[xml]$conf = winrm get winrm/config/client -format:pretty
68+
$trustedHosts = $conf.Client.TrustedHosts.Split(',')
69+
if ($trustedHosts -contains $containerName) {
70+
Write-Host "Removing $containerName from trusted hosts ($($trustedHosts -join ','))"
71+
winrm set winrm/config/client "@{TrustedHosts=""$(@($trustedHosts | Where-Object { $_ -ne $containerName }) -join ',')""}" | Out-Null
72+
}
73+
}
74+
catch {}
75+
}
76+
6577
if ($myVolume) {
6678
Write-Host "Removing volume $myVolumeName"
6779
docker volume remove $myVolumeName

0 commit comments

Comments
 (0)