chocolatey / chocolatey-licensed-issues

Issues for Licensed Editions of Chocolatey
19 stars 13 forks source link

Central Management - Unable to install chocolatey-management-service package under certain conditions #242

Closed sync-by-unito[bot] closed 2 years ago

sync-by-unito[bot] commented 2 years ago

Description

Following the release of the 0.6.0 version of Chocolatey Central Management, depending on the current configuration/setup of a machine, the chocolatey-management-service package can fail to install, with the following error:

image

Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32".

The problematic piece of code is the following:

$portList = [System.Collections.Generic.HashSet[int]]@(
    # Get Port Number(s) from firewall rule, if any
    Get-NetFirewallRule -DisplayName "Chocolatey Central Management Port" -ErrorAction Ignore |
        Get-NetFirewallPortFilter |
        Select-Object -ExpandProperty LocalPort

    # Get Port Number from chocolatey.config file
    if ($env:ChocolateyInstall) {
        $configFile = Join-Path $env:ChocolateyInstall -ChildPath "config/chocolatey.config"

        if (Test-Path -Path $configFile) {
            [xml]$xml = Get-Content -Path $configFile
            $xml.chocolatey.config.add |
                Where-Object { $_.key -eq 'centralManagementServiceUrl' -And -Not [String]::IsNullOrEmpty($_.value) } |
                ForEach-Object {
                    ([uri]$_.value).Port
                }
        }
    }
)

This portList is used to establish a list of port that need to be removed from netsh entries, however, it can fail to establish what these ports are.

If a firewall rule and entry in the chocolatey.config file is found, then the portList is created correctly. If a firewall rule doesn't exist and and entry in the choocolatey.config doesn't exist, then the portList is created correctly If a firewall rule exists and no entry in the chocolatey.config exists, then the portList errors If a firewall rule doesn't exist and an entry in the chocollatey.config exists, the the portList errors

Steps To Reproduce

  1. Find a machine that doesn't currently have the CCM Service installed
  2. Run the following code to remove any firewall rules that might exist
$firewallPorts = Get-NetFirewallRule |   
    Where-Object { $_.DisplayName -eq "Chocolatey Central Management Port" } |   
    Get-NetFirewallPortFilter   
$firewallPorts | Remove-NetFirewallRule   
  1. Run the following code to ensure no firewall rules exist
Get-NetFirewallRule -DisplayName "Chocolatey Central Management Port" -ErrorAction Ignore |   
        Get-NetFirewallPortFilter |   
        Select-Object -ExpandProperty LocalPort   
  1. Run the following code to ensure no entry in the chocolatey.config file for the CCM Service URL
choco config unset --name=centralManagementServiceUrl   
  1. Run the following code to ensure entry is empty
choco config get --name=centralManagementServiceUrl   
  1. Run the following to verify that it correctly returns nothing
$portList = [System.Collections.Generic.HashSet[int]]@(
    # Get Port Number(s) from firewall rule, if any
    Get-NetFirewallRule -DisplayName "Chocolatey Central Management Port" -ErrorAction Ignore |
        Get-NetFirewallPortFilter |
        Select-Object -ExpandProperty LocalPort

    # Get Port Number from chocolatey.config file
    if ($env:ChocolateyInstall) {
        $configFile = Join-Path $env:ChocolateyInstall -ChildPath "config/chocolatey.config"

        if (Test-Path -Path $configFile) {
            [xml]$xml = Get-Content -Path $configFile
            $xml.chocolatey.config.add |
                Where-Object { $_.key -eq 'centralManagementServiceUrl' -And -Not [String]::IsNullOrEmpty($_.value) } |
                ForEach-Object {
                    ([uri]$_.value).Port
                }
        }
    }
)
  1. Run the following to set the CCM Service URL
choco config set --name=centralManagementServiceUrl --value=https://chocoserver:24020/ChocolateyManagementService
  1. Run the following to see that portList errors out
$portList = [System.Collections.Generic.HashSet[int]]@(
    # Get Port Number(s) from firewall rule, if any
    Get-NetFirewallRule -DisplayName "Chocolatey Central Management Port" -ErrorAction Ignore |
        Get-NetFirewallPortFilter |
        Select-Object -ExpandProperty LocalPort

    # Get Port Number from chocolatey.config file
    if ($env:ChocolateyInstall) {
        $configFile = Join-Path $env:ChocolateyInstall -ChildPath "config/chocolatey.config"

        if (Test-Path -Path $configFile) {
            [xml]$xml = Get-Content -Path $configFile
            $xml.chocolatey.config.add |
                Where-Object { $_.key -eq 'centralManagementServiceUrl' -And -Not [String]::IsNullOrEmpty($_.value) } |
                ForEach-Object {
                    ([uri]$_.value).Port
                }
        }
    }
)
  1. Run the following to unset the chocolatey.config file
choco config unset --name=centralManagementServiceUrl
  1. Run the following to verify portList works correctly
$portList = [System.Collections.Generic.HashSet[int]]@(
    # Get Port Number(s) from firewall rule, if any
    Get-NetFirewallRule -DisplayName "Chocolatey Central Management Port" -ErrorAction Ignore |
        Get-NetFirewallPortFilter |
        Select-Object -ExpandProperty LocalPort

    # Get Port Number from chocolatey.config file
    if ($env:ChocolateyInstall) {
        $configFile = Join-Path $env:ChocolateyInstall -ChildPath "config/chocolatey.config"

        if (Test-Path -Path $configFile) {
            [xml]$xml = Get-Content -Path $configFile
            $xml.chocolatey.config.add |
                Where-Object { $_.key -eq 'centralManagementServiceUrl' -And -Not [String]::IsNullOrEmpty($_.value) } |
                ForEach-Object {
                    ([uri]$_.value).Port
                }
        }
    }
)
  1. Run the following to create a firewall rule

New-NetFirewallRule -DisplayName "Chocolatey Central Management Port" -Direction Inbound -LocalPort 24020 -Protocol TCP -Action Allow
  1. Run the following to see that portList errors out
$portList = [System.Collections.Generic.HashSet[int]]@(
    # Get Port Number(s) from firewall rule, if any
    Get-NetFirewallRule -DisplayName "Chocolatey Central Management Port" -ErrorAction Ignore |
        Get-NetFirewallPortFilter |
        Select-Object -ExpandProperty LocalPort

    # Get Port Number from chocolatey.config file
    if ($env:ChocolateyInstall) {
        $configFile = Join-Path $env:ChocolateyInstall -ChildPath "config/chocolatey.config"

        if (Test-Path -Path $configFile) {
            [xml]$xml = Get-Content -Path $configFile
            $xml.chocolatey.config.add |
                Where-Object { $_.key -eq 'centralManagementServiceUrl' -And -Not [String]::IsNullOrEmpty($_.value) } |
                ForEach-Object {
                    ([uri]$_.value).Port
                }
        }
    }
)
  1. Run the following to set the chocolatey.config file for CCM Url
choco config set --name=centralManagementServiceUrl --value=https://chocoserver:24020/ChocolateyManagementService
  1. Run the following to verify portList works correctly
$portList = [System.Collections.Generic.HashSet[int]]@(
    # Get Port Number(s) from firewall rule, if any
    Get-NetFirewallRule -DisplayName "Chocolatey Central Management Port" -ErrorAction Ignore |
        Get-NetFirewallPortFilter |
        Select-Object -ExpandProperty LocalPort

    # Get Port Number from chocolatey.config file
    if ($env:ChocolateyInstall) {
        $configFile = Join-Path $env:ChocolateyInstall -ChildPath "config/chocolatey.config"

        if (Test-Path -Path $configFile) {
            [xml]$xml = Get-Content -Path $configFile
            $xml.chocolatey.config.add |
                Where-Object { $_.key -eq 'centralManagementServiceUrl' -And -Not [String]::IsNullOrEmpty($_.value) } |
                ForEach-Object {
                    ([uri]$_.value).Port
                }
        }
    }
)

Output Log

Workarounds

  1. Take a note of the current centralManamgentServiceUrl using the following
choco config get --name=centralManagementServiceUrl
  1. Run the following code to ensure that no firewall rules, or entry in the chocolatey.config file exist
$firewallPorts = Get-NetFirewallRule |     Where-Object { $_.DisplayName -eq "Chocolatey Central Management Port" } |     Get-NetFirewallPortFilter $firewallPorts | Remove-NetFirewallRule

choco config unset --name=centralManagementServiceUrl
  1. Install the package
  2. NOTE: You will need to set the centralManagementServiceUrl back to what it is meant to be

Proposed Solution

Ensure that the portList code works in all possible combinations of values.

Related Issues and Tickets

N/A

Done Checklist

┆Issue is synchronized with this Gitlab issue by Unito ┆Milestone: 0.6.1