diff --git a/CZ.PowerShell.NetworkTools.code-workspace b/CZ.PowerShell.NetworkTools.code-workspace index 28d18da..6fbec76 100644 --- a/CZ.PowerShell.NetworkTools.code-workspace +++ b/CZ.PowerShell.NetworkTools.code-workspace @@ -22,7 +22,9 @@ // for well formatted documentation "docsmsft.docs-authoring-pack", // for good language - "streetsidesoftware.code-spell-checker" + "streetsidesoftware.code-spell-checker", + // for pester tests + "pspester.pester-test" ] } } \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7bf5b15..40c94c0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -6,55 +6,117 @@ trigger: - main -pool: - vmImage: windows-latest - -steps: -- task: PowerShell@2 - displayName: "Run pester tests" - inputs: - targetType: 'inline' - script: | - Install-Module -Scope CurrentUser -Force -AllowClobber -SkipPublisherCheck Pester; - Import-Module Pester; - $configuration = [PesterConfiguration]::Default; - $configuration.CodeCoverage.Enabled = $true; - $configuration.CodeCoverage.Path = (Get-ChildItem src/*.ps1 | ForEach-Object{$_.FullName}); - $configuration.CodeCoverage.OutputFormat = "JaCoCo"; - $configuration.TestResult.Enabled = $true; - $configuration.Run.Exit = $true; - $configuration.Run.Path = (Get-ChildItem tests/*ps1 | ForEach-Object{$_.FullName}); - Invoke-Pester -Configuration $configuration; - showWarnings: true - pwsh: true -- task: PowerShell@2 - displayName: "Build the powershell package" - inputs: - filePath: 'build/build.ps1' - showWarnings: true - pwsh: true -- task: PowerShell@2 - displayName: "Debug files" - inputs: - targetType: 'inline' - script: | - ls -Recurse | select FullName; - showWarnings: true - pwsh: true -- task: PublishBuildArtifacts@1 - inputs: - PathtoPublish: 'src/bin/' - ArtifactName: 'drop' - publishLocation: 'Container' -- task: PublishTestResults@2 - inputs: - testResultsFormat: 'NUnit' - testResultsFiles: 'testResults.xml' - failTaskOnFailedTests: true - testRunTitle: 'CZ.PowerShell.NetworkTools' -- task: PublishCodeCoverageResults@1 - inputs: - codeCoverageTool: 'JaCoCo' - summaryFileLocation: 'coverage.xml' - pathToSources: 'src/' - failIfCoverageEmpty: true \ No newline at end of file +jobs: + - job: 'tests' + strategy: + matrix: + linux: + imageName: 'ubuntu-latest' + mac: + imageName: 'macOS-latest' + windows: + imageName: 'windows-latest' + pool: + vmImage: $(imageName) + steps: + - task: PowerShell@2 + displayName: "Run pester tests" + inputs: + targetType: 'inline' + script: | + Install-Module -Scope CurrentUser -Force -AllowClobber -SkipPublisherCheck Pester; + Import-Module Pester; + $configuration = [PesterConfiguration]::Default; + $configuration.CodeCoverage.Enabled = $true; + $configuration.CodeCoverage.Path = (Get-ChildItem src/*.ps1 | ForEach-Object{$_.FullName}); + $configuration.CodeCoverage.OutputFormat = "JaCoCo"; + $configuration.CodeCoverage.OutputPath = '$(imageName)-coverage.xml' + $configuration.TestResult.Enabled = $true; + $configuration.TestResult.OutputPath = '$(imageName)-testResults.xml' + $configuration.Run.Exit = $true; + $configuration.Run.Path = (Get-ChildItem tests/*ps1 | ForEach-Object{$_.FullName}); + Invoke-Pester -Configuration $configuration; + showWarnings: true + pwsh: true + - task: PublishBuildArtifacts@1 + displayName: 'Publish Coverage' + condition: always() + inputs: + PathtoPublish: '$(imageName)-coverage.xml' + ArtifactName: 'coverage' + publishLocation: Container + - task: PublishBuildArtifacts@1 + displayName: 'Publish Tests' + condition: always() + inputs: + PathtoPublish: '$(imageName)-testResults.xml' + ArtifactName: 'tests' + publishLocation: Container + - job: 'build_package' + pool: + vmImage: windows-latest + dependsOn: + - 'tests' + steps: + - task: PowerShell@2 + displayName: "Build the powershell package" + inputs: + filePath: 'build/build.ps1' + showWarnings: true + pwsh: true + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: 'src/bin/' + ArtifactName: 'drop' + publishLocation: 'Container' + - job: 'publish_coverage_and_tests' + pool: + vmImage: windows-latest + dependsOn: + - 'tests' + steps: + # - task: DownloadBuildArtifacts@0 + # displayName: 'Download Coverage Windows Artifacts' + # inputs: + # artifactName: windows-coverage + # downloadPath: $(System.DefaultWorkingDirectory)/ + # - task: DownloadBuildArtifacts@0 + # displayName: 'Download Coverage Linux Artifacts' + # inputs: + # artifactName: linux-coverage + # downloadPath: $(System.DefaultWorkingDirectory)/ + # - task: DownloadBuildArtifacts@0 + # displayName: 'Download Tests Windows Artifacts' + # inputs: + # artifactName: windows-tests + # downloadPath: $(System.DefaultWorkingDirectory)/ + # - task: DownloadBuildArtifacts@0 + # displayName: 'Download Tests Linux Artifacts' + # inputs: + # artifactName: linux-tests + # downloadPath: $(System.DefaultWorkingDirectory)/ + - task: DownloadBuildArtifacts@1 + displayName: 'Download All Tests Artifacts' + inputs: + artifactName: 'tests' + downloadPath: $(System.DefaultWorkingDirectory)/ + - task: DownloadBuildArtifacts@1 + displayName: 'Download All Coverage Artifacts' + inputs: + artifactName: 'coverage' + downloadPath: $(System.DefaultWorkingDirectory)/ + - task: PublishCodeCoverageResults@1 + condition: always() + inputs: + codeCoverageTool: 'JaCoCo' + summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage/*coverage.xml' + pathToSources: 'src/' + failIfCoverageEmpty: true + - task: PublishTestResults@2 + condition: always() + inputs: + testResultsFormat: 'NUnit' + testResultsFiles: '$(System.DefaultWorkingDirectory)/tests/*testResults.xml' + failTaskOnFailedTests: true + testRunTitle: 'CZ.PowerShell.NetworkTools' + mergeTestResults: true \ No newline at end of file diff --git a/devcontainer.json b/devcontainer.json new file mode 100644 index 0000000..e34ed2d --- /dev/null +++ b/devcontainer.json @@ -0,0 +1,24 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "files.trimTrailingWhitespace": true, + "cSpell.words": [ + "cmdlet", + "paule" + ] + }, + "extensions": { + // for the powershell scripts + "ms-vscode.powershell", + // for the jupiter notebook integration for powershell + "ms-dotnettools.dotnet-interactive-vscode", + // for good language in the docs + "streetsidesoftware.code-spell-checker", + // for well formatted documentation + "docsmsft.docs-authoring-pack" + } +} \ No newline at end of file diff --git a/samples/basic.noproxy.config.json b/samples/basic.noproxy.config.json new file mode 100644 index 0000000..c9816b0 --- /dev/null +++ b/samples/basic.noproxy.config.json @@ -0,0 +1,4 @@ +{ + "ProxyAddress": null, + "BypassList": [] +} \ No newline at end of file diff --git a/samples/basic.proxy.config.json b/samples/basic.proxy.config.json new file mode 100644 index 0000000..bef6858 --- /dev/null +++ b/samples/basic.proxy.config.json @@ -0,0 +1,6 @@ +{ + "ProxyAddress": "http://proxy.codez.one:80", + "BypassList": [ + "git.codez.one" + ] +} \ No newline at end of file diff --git a/samples/basic.systemproxy.json b/samples/basic.systemproxy.json new file mode 100644 index 0000000..37ce968 --- /dev/null +++ b/samples/basic.systemproxy.json @@ -0,0 +1,3 @@ +{ + "UseSystemProxyAddress": true +} \ No newline at end of file diff --git a/src/Set-ProxyConfiguration.ps1 b/src/Set-ProxyConfiguration.ps1 new file mode 100644 index 0000000..fa20eb4 --- /dev/null +++ b/src/Set-ProxyConfiguration.ps1 @@ -0,0 +1,470 @@ +function Set-ProxyConfiguration { + [CmdletBinding()] + param ( + [string] + $ConfigPath, + [switch] + $NoRoot + ) + if ((Test-Path -Path $ConfigPath) -eq $false) { + Write-Error "The config path doesn't exsists." -ErrorAction Stop; + } + [ProxySetting] $proxySettings = [ProxySetting] (Get-Content -Raw -Path $ConfigPath | ConvertFrom-Json); + Write-Debug $proxySettings; + if ($proxySettings.UseSystemProxyAddress -and [string]::IsNullOrWhiteSpace($proxySettings.ProxyAddress)) { + if ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) { + $proxySettings.ProxyAddress = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings').proxyServer; + } + else { + # TODO: find a good way to get linux system proxy. For now throw exception + Write-Error "Currently we don't support linux, to read out the system proxy. Please configure it manualy" -ErrorAction Stop; + } + if ($null -eq $proxySettings.ProxyCredentials) { + Write-Warning "You don't have set proxy credentials. If your system is configured with proxy credentials we can't read them."; + } + } + Set-GitProxyConfiguration -Settings $proxySettings; + Set-NpmProxyConfiguration -Settings $proxySettings; + Set-AptProxyConfiguration -Settings $proxySettings -NoRoot:$NoRoot; + Set-DockerProxyConfiguration -Settings $proxySettings; + Set-PowerShellProxyConfiguration -Settings $proxySettings -NoRoot:$NoRoot; + Set-EnvironmentProxyConfiguration -Settings $proxySettings -NoRoot:$NoRoot; +} + +function Set-GitProxyConfiguration { + [CmdletBinding()] + param ( + [ProxySetting] + $Settings + ) + if ($null -eq (Get-Command "git" -ErrorAction SilentlyContinue)) { + Write-Debug "Unable to find git on your system. Skip configuration"; + return; + } + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # unset base address + . "git" "config" "--global" "--unset" "http.proxy"; + . "git" "config" "--global" "--unset" "https.proxy"; + } + else { + # set base address + . "git" "config" "--global" "http.proxy" "$($Settings.ProxyAddress)"; + . "git" "config" "--global" "https.proxy" "$($Settings.ProxyAddress)"; + + # only git version 2.13 or higher supports hostname wildcards + $supportsWildcardHostnames = ((((git version) -split ' ')[2] -split '\.')[0] -ge 2) -and ((((git version) -split ' ')[2] -split '\.')[1] -ge 13); + # set all new entries + $Settings.BypassList | ForEach-Object { + if ($_.Contains('*') -and $supportsWildcardHostnames -eq $false) { + Write-Warning "Your git version is to old to support wild card hostnames. You must have version 2.13 or higher. We skip the hostname $_"; + } + else { + if ($_.StartsWith("https")) { + . "git" "config" "--global" "https.$_.proxy" '""'; + } + elseif ($_.StartsWith("http")) { + . "git" "config" "--global" "http.$_.proxy" '""'; + } + else { + . "git" "config" "--global" "http.http://$_.proxy" '""'; + . "git" "config" "--global" "https.https://$_.proxy" '""'; + } + } + + } + } + # remove old bypasses entries: + # http + . "git" "config" "--global" "--get-regexp" "http\.http" | ForEach-Object { + $bypasskey = $_.Trim(); + if ($bypasskey -match "(http\.)(http.*)(\.proxy)") { + $bypassedUrl = $matches[2].Trim(); + $shouldBeRemoved = $null -eq ($Settings.BypassList | Where-Object { "http://$_" -like $bypassedUrl }); + if ($shouldBeRemoved) { + Write-Warning "Remove '$bypassedUrl' from git bypass list"; + . "git" "config" "--global" "--unset" "$bypasskey"; + } + } + } + + # https + . "git" "config" "--global" "--get-regexp" "https\.https" | ForEach-Object { + $bypasskey = $_.Trim(); + if ($bypasskey -match "(https\.)(https.*)(\.proxy)") { + $bypassedUrl = $Matches[2].Trim(); + $shouldBeRemoved = $null -eq ($Settings.BypassList | Where-Object { "https://$_" -like $bypassedUrl }); + if ($shouldBeRemoved) { + Write-Warning "Remove '$bypassedUrl' from git bypass list"; + . "git" "config" "--global" "--unset" "$bypasskey"; + } + } + } +} + +function Set-NpmProxyConfiguration { + [CmdletBinding()] + param ( + [ProxySetting] + $Settings + ) + $npmCommand = (Get-Command "npm" -ErrorAction SilentlyContinue); + if ($null -eq $npmCommand) { + Write-Debug "Unable to find npm on your system. Skip configuration"; + return; + } + if ($npmCommand.Path.StartsWith('/mnt/c/Program Files/')) { + Write-Warning ("In WSL2 you must override your environment variables to the linux version of NPM. " + ` + "We can't currently configure NPM for you."); + return; + } + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # unset base address + . "npm" "config" "delete" "proxy"; + . "npm" "config" "delete" "https-proxy" + # TODO: only set the right format + . "npm" "config" "delete" "no-proxy"; # this is for npm version < 6.4.1 + . "npm" "config" "delete" "noproxy"; # this is for npm verison >= 6.4.1 + } + else { + # set base address + . "npm" "config" "set" "proxy" "$($Settings.ProxyAddress)" | Out-Null; + . "npm" "config" "set" "https-proxy" "$($Settings.ProxyAddress)" | Out-Null; + + $bypasstring = $(($Settings.BypassList -join ',').Trim()); + # TODO: only set the right format + . "npm" "config" "set" "no-proxy" "$bypasstring" | Out-Null; # this is for npm version < 6.4.1 + . "npm" "config" "set" "noproxy" $bypasstring | Out-Null; # this is for npm verison >= 6.4.1 + } + +} + +function Set-AptProxyConfiguration { + [CmdletBinding()] + param ( + [ProxySetting] + $Settings, + [switch] + $NoRoot + ) + if ($null -eq (Get-Command "apt" -ErrorAction SilentlyContinue)) { + Write-Debug "Unable to find apt on your system. Skip configuration"; + return; + } + try { + if ((Test-Path "/etc/apt/apt.conf") -eq $false) { + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # do nothing if no proxy should be configured and the config file don't exsists. + return; + } + # just write the proxy into the file if it doesn't exsists + "Acquire::http::Proxy ""$($Settings.ProxyAddress)"";" | Set-Content "/etc/apt/apt.conf"; + } + else { + $isAProxyAlreadConfigured = $null -ne (. "apt-config" "dump" "Acquire::http::proxy"); + $regexOptions = [System.Text.RegularExpressions.RegexOptions]([System.Text.RegularExpressions.RegexOptions]::Multiline); + $regexSimplePattern = "Acquire::http::Proxy .*;"; + $regexComplexPattern = "(^Acquire.*{(.|\n)*http.*{(.|\n)*)(proxy "".+"";)((.|\n)*}(.|\n)*})$"; + $regexSimple = New-Object System.Text.RegularExpressions.Regex $regexSimplePattern, $regexOptions; + $regexComplex = New-Object System.Text.RegularExpressions.Regex $regexComplexPattern, $regexOptions; + if ($isAProxyAlreadConfigured) { + $aptConfig = Get-Content "/etc/apt/apt.conf"; + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # delete proxy config + $aptConfig = $regexSimple.Replace($aptConfig, ""); + $aptConfig = $regexComplex.Replace($aptConfig, "`${1}`${5}"); + } + else { + # add proxy config + $aptConfig = $regexSimple.Replace($aptConfig, "Acquire::http::Proxy ""$($Settings.ProxyAddress)"";"); + $aptConfig = $regexComplex.Replace($aptConfig, "`${1}Proxy `"$($Settings.ProxyAddress)`";`${5}"); + } + # replace the file with new content + Write-Warning $aptConfig; + $aptConfig | Set-Content "/etc/apt/apt.conf"; + } + else { + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # it's okay if no proxy is configured + return; + } + else { + # if no proxy is configured just append the line + "Acquire::http::Proxy ""$($Settings.ProxyAddress)"";" | Add-Content -Encoding ascii -NoNewline -Path "/etc/apt/apt.conf"; + } + } + } + if ($null -ne $Settings.BypassList -and $Settings.BypassList.Count -ne 0) { + Write-Warning "apt-get does not support bypass list. To bypass the proxy config for a given command start the command like: 'apt-get -o Acquire::http::proxy=false ....'. This will bypass the proxy for the runtime of the apt-get command."; + } + } + catch [System.UnauthorizedAccessException] { + if ($NoRoot) { + Write-Debug "Skip APT configuration because NORoot Option is set."; + return; + } + else { + Write-Error "You must be root to change APT settings." -TargetObject $_ -RecommendedAction "Run powershell as root or specify the `NoRoot` switch." -ErrorAction Stop; + return; + } + } + + +} + +function Set-DockerProxyConfiguration { + [CmdletBinding()] + param ( + [ProxySetting] + $Settings + ) + if ($null -eq (Get-Command "docker" -ErrorAction SilentlyContinue)) { + Write-Debug "Unable to find docker on your system. Skip configuration"; + return; + } + $json = '{ + "proxies": + { + "default": + { + "httpProxy": "' + $Settings.ProxyAddress + '", + "httpsProxy": "' + $Settings.ProxyAddress + '", + "noProxy": "' + ($Settings.BypassList -join ',') + '" + } + } + }'; + Write-Verbose "$json"; + $proxyConfig = ConvertFrom-Json $json; + if ((Test-Path "~/.docker/config.json")) { + $dockerConfig = (Get-Content "~/.docker/config.json" -Raw | ConvertFrom-Json); + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress) -and [bool]($dockerConfig.PSobject.Properties.name -match "proxies")) { + $dockerConfig.PSobject.Properties.Remove('proxies'); + } + elseif ($false -eq [bool]($dockerConfig.PSobject.Properties.name -match "proxies")) { + $dockerConfig | Add-Member -MemberType NoteProperty -Name "proxies" -Value $proxyConfig.proxies; + } + elseif ($false -eq [bool]($dockerConfig.proxies.PSobject.Properties.name -match "default")) { + + $dockerConfig.proxies | Add-Member -MemberType NoteProperty -Name "default" -Value $proxyConfig.proxies.default; + } + else { + $dockerConfig.proxies.default | Add-Member -NotePropertyName "httpProxy" -NotePropertyValue $Settings.ProxyAddress -Force + $dockerConfig.proxies.default | Add-Member -NotePropertyName "httpsProxy" -NotePropertyValue $Settings.ProxyAddress -Force + $dockerConfig.proxies.default | Add-Member -NotePropertyName "noProxy" -NotePropertyValue ($Settings.BypassList -join ',') -Force + } + ConvertTo-Json $dockerConfig | Set-Content "~/.docker/config.json"; + } + else { + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # no proxy should be configured. + return; + } + New-Item "~/.docker" -Force -ItemType Directory | Out-Null; + ConvertTo-Json $proxyConfig | Set-Content "~/.docker/config.json" -Force; + } +} + +function Set-PowerShellProxyConfiguration { + [CmdletBinding()] + param ( + [ProxySetting] + $Settings, + [switch] + $NoRoot + ) + if ($NoRoot) { + Write-Verbose "You can't set a proxy for powershell 5 / 7 without admin / root rights. On Windows try to set IE Settings if this is possible."; + return; + } + if ($Settings.BypassList -ne $null -and $Settings.BypassList.Count -gt 0) { + $bypasslist = ' + '+ ( + (($Settings.BypassList | ForEach-Object { " " }) -join [System.Environment]::NewLine) + ) + ' + '; + } + + $proxyConfig = ' + + + + '+ $bypasslist + ' + + + '; + Write-Debug "$proxyConfig"; + $powershellConfigExtension = [xml]$proxyConfig; + function Update-PowerShellConfig { + [CmdletBinding()] + param ( + [Parameter()] + [string] + $powershellPath + ) + + $configPath = "$powershellPath.config"; + if ((Test-Path $configPath) -eq $false -and [string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # do nothing, if the config isn't exsist and no proxy is required. + return + } + #create file if it isn't exsists + if ((Test-Path $configPath) -eq $false) { + # set acls for windows + if ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) { + $installDir = (Get-Item $powershellPath).Directory.FullName; + # allow write access to the config file and save the file + $defaultAcl = Get-Acl "$installDir"; + $aclForPowerShellFile = Get-Acl "$installDir"; + $AdministratorsSID = New-Object System.Security.Principal.SecurityIdentifier 'S-1-5-32-544'; + $newRule = New-Object System.Security.AccessControl.FileSystemAccessRule($AdministratorsSID, @("Write"), "None", "InheritOnly", "Allow") ; + $aclForPowerShellFile.AddAccessRule($newRule); + Set-Acl -Path "$installDir" $aclForPowerShellFile; + } + New-Item $configPath -ItemType File | Out-Null; + if ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) { + #revoke access to default: + Set-Acl -Path "$installDir" $defaultAcl | Out-Null; + } + } + + # set acls for windows + if ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) { + # allow write access to the config file and save the file + $defaultAcl = Get-Acl "$configPath"; + $aclForPowerShellFile = Get-Acl "$configPath"; + $AdministratorsSID = New-Object System.Security.Principal.SecurityIdentifier 'S-1-5-32-544'; + $newRule = New-Object System.Security.AccessControl.FileSystemAccessRule($AdministratorsSID, @("Write"), "None", "InheritOnly", "Allow") ; + $aclForPowerShellFile.AddAccessRule($newRule); + Set-Acl -Path "$configPath" $aclForPowerShellFile; + } + $powershellConfig = [xml](Get-Content "$configPath"); + if ($null -eq $powershellConfig) { + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # no proxy should be confgiured + return; + } + else { + $proxyConfig | Set-Content $configPath; + } + } + elseif ($null -eq $powershellConfig.configuration -and $false -eq [string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + $extensionNode = $powershellConfig.ImportNode($powershellConfigExtension.configuration, $true); + $powershellConfig.AppendChild($extensionNode) | Out-Null; + } + elseif ($null -eq $powershellConfig.configuration.'system.net' -and $false -eq [string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + $extensionNode = $powershellConfig.configuration.OwnerDocument.ImportNode($powershellConfigExtension.configuration.'system.net', $true); + $powershellConfig.configuration.AppendChild($extensionNode) | Out-Null; + } + else { + # remove old proxy config + $configuredDefaultProxy = $powershellConfig.configuration.GetElementsByTagName('system.net')[0].GetElementsByTagName("defaultProxy"); + if ($null -ne $configuredDefaultProxy -and $configuredDefaultProxy.Count -gt 0) { + $powershellConfig.configuration.GetElementsByTagName('system.net')[0].RemoveChild($configuredDefaultProxy[0]) | Out-Null; + } + if ($false -eq [string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # add new proxy config + $extensionNode = $powershellConfig.configuration.GetElementsByTagName('system.net')[0].OwnerDocument.ImportNode($powershellConfigExtension.configuration.'system.net'.defaultProxy, $true); + $powershellConfig.configuration.GetElementsByTagName('system.net')[0].AppendChild($extensionNode) | Out-Null; + } + } + if ($null -ne $powershellConfig) { + $powershellConfig.Save("$configPath") | Out-Null; + } + if ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) { + #revoke access to default: + Set-Acl -Path "$configPath" $defaultAcl | Out-Null; + } + } + + # pwsh core + $powershell = (Get-Command "pwsh" -ErrorAction SilentlyContinue); + if ($null -eq $powershell) { + Write-Debug "Unable to find PowerShell 7 on your system. Skip configuration"; + } + else { + Update-PowerShellConfig -powershellPath ($powershell.Path); + } + + #Win powershell + $winPowershell = (Get-Command "powershell" -ErrorAction SilentlyContinue); + if ($null -eq $winPowershell) { + Write-Debug "Unable to find PowerShell < 6 on your system. Skip configuration"; + } + else { + Update-PowerShellConfig -powershellPath ($winPowershell.Path); + } + +} + +function Set-EnvironmentProxyConfiguration { + [CmdletBinding()] + param ( + [Parameter()] + [ProxySetting] + $Settings, + [switch] + $NoRoot + ) + if ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) { + # set the process to, to avoid the user must restart the process. + [Environment]::SetEnvironmentVariable("HTTP_PROXY", $Settings.ProxyAddress, [EnvironmentVariableTarget]::Process) + [Environment]::SetEnvironmentVariable("HTTPS_PROXY", $Settings.ProxyAddress, [EnvironmentVariableTarget]::Process) + [Environment]::SetEnvironmentVariable("NO_PROXY", $($Settings.BypassList -join ','), [EnvironmentVariableTarget]::Process) + if ($NoRoot) { + [Environment]::SetEnvironmentVariable("HTTPS_PROXY", $Settings.ProxyAddress, [EnvironmentVariableTarget]::User) + [Environment]::SetEnvironmentVariable("HTTP_PROXY", $Settings.ProxyAddress, [EnvironmentVariableTarget]::User) + [Environment]::SetEnvironmentVariable("NO_PROXY", $($Settings.BypassList -join ','), [EnvironmentVariableTarget]::User) + } + else { + # Set environment for all users + [Environment]::SetEnvironmentVariable("HTTP_PROXY", $Settings.ProxyAddress, [EnvironmentVariableTarget]::Machine); + [Environment]::SetEnvironmentVariable("HTTPS_PROXY", $Settings.ProxyAddress, [EnvironmentVariableTarget]::Machine); + [Environment]::SetEnvironmentVariable("NO_PROXY", $($Settings.BypassList -join ','), [EnvironmentVariableTarget]::Machine) + } + + } + else { + if ($NoRoot) { + Write-Warning "Currently to set the environment this script needs root rights. Didn't change any environment varables."; + # TODO: add user proxy settings for this case. + + } + else { + # Set environment for all users + $proxyshFilePath = "/etc/profile.d/proxy.sh"; + if ([string]::IsNullOrWhiteSpace($Settings.ProxyAddress)) { + # Remove this content from the file, because a line with: + # `something=` + # is an error for some tools. So the lines must be empty + if (Test-Path -Path $proxyshFilePath) { + Remove-Item -Path "/etc/profile.d/proxy.sh" -Force; + Write-Verbose "$proxyshFilePath deleted. Proxy settings are resetted."; + } + else { + Write-Verbose "$proxyshFilePath didn't exsist. Nothing changed."; + } + + } + else { + "export http_proxy=$($Settings.ProxyAddress) + export no_proxy=$($Settings.BypassList -join ',') + export HTTP_PROXY=$($Settings.ProxyAddress) + export https_proxy=$($Settings.ProxyAddress) + export HTTPS_PROXY=$($Settings.ProxyAddress)" | Set-Content -Path $proxyshFilePath; + } + } + } +} + +class ProxySetting { + # TODO: implement http and https proxies can be different! 💣 + [string] $ProxyAddress = $null; + # TODO: how to handle credentials + [pscredential] $ProxyCredentials = $null; + # TODO: are we allowed to override system proxy. (important for all .net applications, because they normaly use the system settings) + [bool] $UseSystemProxyAddress = $false; + [string[]] $BypassList; +} \ No newline at end of file diff --git a/tests/Set-ProxyConfiguration.tests.ps1 b/tests/Set-ProxyConfiguration.tests.ps1 new file mode 100644 index 0000000..0ec43c9 --- /dev/null +++ b/tests/Set-ProxyConfiguration.tests.ps1 @@ -0,0 +1,1152 @@ +Describe "Set-ProxyConfiguration" { + BeforeDiscovery { + $script:skipBecauseLinux = ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) -eq $false; + $script:skipBecauseWindows = ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) -eq $true; + $script:noapt = ($null -eq (Get-Command apt -ErrorAction SilentlyContinue) -or $null -eq (Get-Command apt-config -ErrorAction SilentlyContinue)); + } + BeforeAll { + # load function to test + $fileInfo = Get-ChildItem $PSCommandPath; + $functionName = $fileInfo.Name.Split('.')[0]; + $file = Get-ChildItem "$PSScriptRoot/../src/$functionName.ps1"; + $targetFileName = "$($file.FullName)"; + # load function to test + . "$targetFileName"; + } + Describe "the main function" { + + Context "When Set-ProxyConfiguration is okay and" { + BeforeAll { + Mock -Verifiable Test-Path { + return $true; + }; + Mock -Verifiable Set-GitProxyConfiguration {}; + Mock -Verifiable Set-NpmProxyConfiguration {}; + Mock -Verifiable Set-AptProxyConfiguration {}; + Mock -Verifiable Set-DockerProxyConfiguration {}; + Mock -Verifiable Set-PowerShellProxyConfiguration {}; + Mock -Verifiable Set-EnvironmentProxyConfiguration {}; + } + It("It Should set the proxy") { + # Arrange + $ProxyAddress = 'http://proxy.codez.one:8080'; + Mock -Verifiable Get-Content { return '{ + "ProxyAddress": "'+ $ProxyAddress + '" + }' + } + $configPath = "something/that/not/exsists"; + # Act + Set-ProxyConfiguration -ConfigPath "$configPath"; + #Assert + Assert-MockCalled Test-Path -Times 1 -ParameterFilter { $Path -eq $configPath }; + Assert-MockCalled Get-Content -Times 1 -ParameterFilter { $Path -eq $configPath -and $Raw -eq $true }; + Assert-MockCalled Set-GitProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress }; + Assert-MockCalled Set-NpmProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress }; + Assert-MockCalled Set-AptProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress -and $NoRoot -eq $false }; + Assert-MockCalled Set-DockerProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress }; + Assert-MockCalled Set-PowerShellProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress -and $NoRoot -eq $false }; + Assert-MockCalled Set-EnvironmentProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress -and $NoRoot -eq $false }; + } + It("It Should set the BypassList") { + # Arrange + $BypassAddresses = 'git.codez.one'; + Mock -Verifiable Get-Content { return '{ + "ProxyAddress": "http://proxy.codez.one:8080", + "BypassList": [ + "'+ $BypassAddresses + '" + ] + }' + } + $configPath = "something/that/not/exsists"; + # Act + Set-ProxyConfiguration -ConfigPath "$configPath"; + #Assert + Assert-MockCalled Test-Path -Times 1 -ParameterFilter { $Path -eq $configPath }; + Assert-MockCalled Get-Content -Times 1 -ParameterFilter { $Path -eq $configPath -and $Raw -eq $true }; + Assert-MockCalled Set-GitProxyConfiguration -Times 1 -ParameterFilter { $Settings.BypassList.Contains($BypassAddresses) }; + Assert-MockCalled Set-NpmProxyConfiguration -Times 1 -ParameterFilter { $Settings.BypassList.Contains($BypassAddresses) }; + Assert-MockCalled Set-AptProxyConfiguration -Times 1 -ParameterFilter { $Settings.BypassList.Contains($BypassAddresses) -and $NoRoot -eq $false }; + Assert-MockCalled Set-DockerProxyConfiguration -Times 1 -ParameterFilter { $Settings.BypassList.Contains($BypassAddresses) }; + Assert-MockCalled Set-PowerShellProxyConfiguration -Times 1 -ParameterFilter { $Settings.BypassList.Contains($BypassAddresses) -and $NoRoot -eq $false }; + Assert-MockCalled Set-EnvironmentProxyConfiguration -Times 1 -ParameterFilter { $Settings.BypassList.Contains($BypassAddresses) -and $NoRoot -eq $false }; + } + It("It Should set the Proxy with the system settings on windows") -Skip:($skipBecauseLinux) { + # Arrange + $ProxyAddress = 'http://proxy.codez.one:8080'; + Mock -Verifiable Get-Content { return '{ + "UseSystemProxyAddress": true + }' + } + Mock -Verifiable Get-ItemProperty { + return [PSCustomObject]@{ + proxyServer = "$ProxyAddress"; + }; + } + $configPath = "something/that/not/exsists"; + # Act + Set-ProxyConfiguration -ConfigPath "$configPath"; + #Assert + Assert-MockCalled Test-Path -Times 1 -ParameterFilter { $Path -eq $configPath }; + Assert-MockCalled Get-Content -Times 1 -ParameterFilter { $Path -eq $configPath -and $Raw -eq $true }; + Assert-MockCalled Get-ItemProperty -Times 1 -ParameterFilter { $Path -eq 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' }; + Assert-MockCalled Set-GitProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress }; + Assert-MockCalled Set-NpmProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress }; + Assert-MockCalled Set-AptProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress -and $NoRoot -eq $false }; + Assert-MockCalled Set-DockerProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress }; + Assert-MockCalled Set-PowerShellProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress -and $NoRoot -eq $false }; + Assert-MockCalled Set-EnvironmentProxyConfiguration -Times 1 -ParameterFilter { $Settings.ProxyAddress -eq $ProxyAddress -and $NoRoot -eq $false }; + } + } + Context "When Set-ProxyConfiguration is not okay and" { + It("It Should write an error if the config file doesn't exsists.") { + Mock -Verifiable Test-Path { + return $false; + }; + $configPath = "something/that/not/exsists"; + # Act & assert + { Set-ProxyConfiguration -ConfigPath "$configPath" } | Should -Throw "The config path doesn't exsists."; + Assert-MockCalled Test-Path -Times 1 -ParameterFilter { $Path -eq $configPath }; + + } + It("It Should write an error if it wants to use system proxy on linux.") -Skip:($skipBecauseWindows) { + Mock -Verifiable Test-Path { + return $true; + }; + Mock -Verifiable Get-Content { return '{ + "UseSystemProxyAddress": true + }' + } + $configPath = "something/that/not/exsists"; + # Act & assert + { Set-ProxyConfiguration -ConfigPath "$configPath" } | Should -Throw "Currently we don't support linux, to read out the system proxy. Please configure it manualy"; + Assert-MockCalled Test-Path -Times 1 -ParameterFilter { $Path -eq $configPath }; + Assert-MockCalled Get-Content -Times 1 -ParameterFilter { $Path -eq $configPath -and $Raw -eq $true }; + } + } + } + Describe "the git function"{ + Context "When Set-GitProxyConfiguration is okay and"{ + It("'git' is undefined, it shouldn't throw an error."){ + Mock -Verifiable Get-Command { + Write-Error "not found"; + } + Mock -Verifiable "git" { + return; + } + # act + Set-GitProxyConfiguration -Settings $null; + #assert + Assert-MockCalled Get-Command -Times 1 -ParameterFilter {$Name -eq "git"}; + Assert-MockCalled "git" -Exactly -Times 0; + } + It("no proxy should be setted, the proxy should be unset."){ + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable "git" { + if($args[2] -eq "--get-regexp"){ + if($args[3] -eq "http\.http"){ + "http.http://codez.one.proxy "; + }else{ + "https.https://codez.one.proxy "; + } + } + return; + } + # act + Set-GitProxyConfiguration -Settings $null; + #assert + Assert-MockCalled Get-Command -Times 1 -ParameterFilter {$Name -eq "git"}; + ## reset proxy entries + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--unset" -and $args[3] -eq "http.proxy"}; + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--unset" -and $args[3] -eq "https.proxy"}; + ## reset bypass + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--get-regexp" -and $args[3] -eq "http\.http"}; + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--get-regexp" -and $args[3] -eq "https\.https"}; + ## the removed bypassed is trimmed and in the right way combined + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--unset" -and $args[3] -eq "http.http://codez.one.proxy"}; + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--unset" -and $args[3] -eq "https.https://codez.one.proxy"}; + ## at the end there should be not more then 6 calls + Assert-MockCalled "git" -Times 6 -Exactly; + } + It("a proxy configuration is required all git commands are running"){ + # arrange + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable "git" { + if($args[2] -eq "--get-regexp"){ + if($args[3] -eq "http\.http"){ + "http.http://not.okay.proxy "; + }else{ + "https.https://not.okay.proxy "; + } + } + if($args[0] -eq "version"){ + return "git version 200.250.100" + } + return; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "http://codez.one", "https://codez.one"; + # act + Set-GitProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -ParameterFilter {$Name -eq "git"}; + ## set proxy entries + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "http.proxy" -and $args[3] -eq $settings.ProxyAddress}; + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "https.proxy" -and $args[3] -eq $settings.ProxyAddress}; + ## set new bypass entries + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "http.http://codez.one.proxy"}; + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "https.https://codez.one.proxy"}; + ## reset old bypass + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--get-regexp" -and $args[3] -eq "http\.http"}; + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--get-regexp" -and $args[3] -eq "https\.https"}; + ## the removed bypassed is trimmed and in the right way combined + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--unset" -and $args[3] -eq "http.http://not.okay.proxy"}; + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "--unset" -and $args[3] -eq "https.https://not.okay.proxy"}; + ## git version is called + Assert-MockCalled "git" -Times 2 -Exactly -ParameterFilter {$args[0] -eq 'version'}; + ## at the end there should be not more then 6 calls + Assert-MockCalled "git" -Times 10 -Exactly; + } + It("bypass entry without protocoll is provided, it should set http and https"){ + # arrange + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable "git" { + return; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "codez.one"; + # act + Set-GitProxyConfiguration -Settings $settings; + ## set new bypass entries + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "http.http://codez.one.proxy"}; + Assert-MockCalled "git" -Times 1 -Exactly -ParameterFilter {$args[0] -eq 'config' -and $args[1] -eq "--global" -and $args[2] -eq "https.https://codez.one.proxy"}; + } + it("get version is to old for wildcard, it should warn the user."){ + # arrange + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable "git" { + if($args[0] -eq "version"){ + return "git version 2.0.100" + } + return; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one"; + # act + Set-GitProxyConfiguration -Settings $settings -WarningVariable warning; + # assert + $warning | Should -Be "Your git version is to old to support wild card hostnames. You must have version 2.13 or higher. We skip the hostname $($settings.BypassList[0])" + } + } + ## TODO: add tests if the bypass list isn't clean + } + Describe "the npm function"{ + Context "When Set-NpmProxyConfiguration is okay and"{ + It("'npm' is undefined, it shouldn't throw an error."){ + Mock -Verifiable Get-Command { + Write-Error "not found"; + } + Mock -Verifiable "npm" { + return; + } + # act + Set-NpmProxyConfiguration -Settings $null; + #assert + Assert-MockCalled Get-Command -Times 1 -ParameterFilter {$Name -eq "npm"}; + Assert-MockCalled "npm" -Exactly -Times 0; + } + It("wsl is active and npm on the path, is the windows npm, it should write an warning."){ + Mock -Verifiable Get-Command { + return [pscustomobject]@{Path = "/mnt/c/Program Files/nodejs/npm"}; + } + Mock -Verifiable "npm" { + return; + } + # act + Set-NpmProxyConfiguration -Settings $null -WarningVariable warning; + #assert + Assert-MockCalled Get-Command -Times 1 -ParameterFilter {$Name -eq "npm"}; + $warning | Should -Be ("In WSL2 you must override your environment variables to the linux version of NPM. " + ` + "We can't currently configure NPM for you."); + Assert-MockCalled "npm" -Exactly -Times 0; + } + It("no proxy setting is defined, it should reset all npm proxy settings."){ + Mock -Verifiable Get-Command { + return [pscustomobject]@{Path = "something"}; + } + Mock -Verifiable "npm" { + return; + } + # act + Set-NpmProxyConfiguration -Settings $null -WarningVariable warning; + #assert + Assert-MockCalled Get-Command -Times 1 -ParameterFilter {$Name -eq "npm"}; + ## remove all proxy settings + Assert-MockCalled "npm" -Times 1 -ParameterFilter {$args[0] -eq "config" -and $args[1] -eq "delete" -and $args[2] -eq "proxy"}; + Assert-MockCalled "npm" -Times 1 -ParameterFilter {$args[0] -eq "config" -and $args[1] -eq "delete" -and $args[2] -eq "https-proxy"}; + Assert-MockCalled "npm" -Times 1 -ParameterFilter {$args[0] -eq "config" -and $args[1] -eq "delete" -and $args[2] -eq "no-proxy"}; + Assert-MockCalled "npm" -Times 1 -ParameterFilter {$args[0] -eq "config" -and $args[1] -eq "delete" -and $args[2] -eq "noproxy"}; + Assert-MockCalled "npm" -Exactly -Times 4; + } + It("and proxy settings are defined, it should set all npm proxy settings."){ + Mock -Verifiable Get-Command { + return [pscustomobject]@{Path = "something"}; + } + Mock -Verifiable "npm" { + return; + } + # act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + Set-NpmProxyConfiguration -Settings $settings -WarningVariable warning; + #assert + Assert-MockCalled Get-Command -Times 1 -ParameterFilter {$Name -eq "npm"}; + ## remove all proxy settings + Assert-MockCalled "npm" -Times 1 -ParameterFilter {$args[0] -eq "config" -and $args[1] -eq "set" -and $args[2] -eq "proxy" -and $args[3] -eq $settings.ProxyAddress}; + Assert-MockCalled "npm" -Times 1 -ParameterFilter {$args[0] -eq "config" -and $args[1] -eq "set" -and $args[2] -eq "https-proxy" -and $args[3] -eq $settings.ProxyAddress}; + Assert-MockCalled "npm" -Times 1 -ParameterFilter {$args[0] -eq "config" -and $args[1] -eq "set" -and $args[2] -eq "no-proxy" -and $args[3] -eq $(($settings.BypassList -join ',').Trim())}; + Assert-MockCalled "npm" -Times 1 -ParameterFilter {$args[0] -eq "config" -and $args[1] -eq "set" -and $args[2] -eq "noproxy" -and $args[3] -eq $(($settings.BypassList -join ',').Trim())}; + Assert-MockCalled "npm" -Exactly -Times 4; + } + } + } + Describe "the apt function"{ + Context "When Set-AptProxyConfiguration is okay and" -Skip:(($skipBecauseWindows) -or ($noapt)){ + It("'apt' is undefined, it shouldn't throw an error"){ + # arrage + Mock -Verifiable Get-Command { + Write-Error "not found"; + } + #act + Set-AptProxyConfiguration -Settings $null; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + } + It("no config exsists and no proxy are required, do nothing."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable Set-Content { + return; + } + #act + Set-AptProxyConfiguration -Settings $null; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + Assert-MockCalled Set-Content -Times 0 -Exactly; + } + It("no config exsists and a proxy is required, write the config."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable Set-Content { + return; + } + #act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + Set-AptProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Value -eq "Acquire::http::Proxy ""$($settings.ProxyAddress)"";"}; + } + It("no config exsists and a proxy with bypass is required, write a warning that bypass is not support by apt."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable Set-Content { + return; + } + #act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + Set-AptProxyConfiguration -Settings $settings -WarningVariable warning; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Value -eq "Acquire::http::Proxy ""$($settings.ProxyAddress)"";"}; + $warning | Should -Be "apt-get does not support bypass list. To bypass the proxy config for a given command start the command like: 'apt-get -o Acquire::http::proxy=false ....'. This will bypass the proxy for the runtime of the apt-get command."; + } + It("config exsists but is empty and a proxy is required, write the config."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Add-Content { + return; + } + Mock -Verifiable "apt-config" { + return $null; + } + #act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + Set-AptProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + Assert-MockCalled "apt-config" -Times 1 -Exactly -ParameterFilter {$Args[0] -eq "dump" -and $Args[1] -eq "Acquire::http::proxy"}; + Assert-MockCalled Add-Content -Times 1 -Exactly -ParameterFilter {$Value -eq "Acquire::http::Proxy ""$($settings.ProxyAddress)"";" -and $Encoding -eq [System.Text.Encoding]::ASCII}; + } + It("config exsists but is empty and a no proxy is required, do nothing."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Add-Content { + return; + } + Mock -Verifiable "apt-config" { + return $null; + } + #act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = $null; + Set-AptProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + Assert-MockCalled "apt-config" -Times 1 -Exactly -ParameterFilter {$Args[0] -eq "dump" -and $Args[1] -eq "Acquire::http::proxy"}; + Assert-MockCalled Add-Content -Times 0 -Exactly; + } + It("config exsists but isn't empty and a no proxy is required, clean up the proxy settings."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Get-Content { + return "Acquire::http::Proxy ""http://old.proxy:80"";" + [System.Environment]::NewLine + + "Acquire {" + [System.Environment]::NewLine + + "http {" + [System.Environment]::NewLine + + "proxy ""http://old.proxy:80"";" + [System.Environment]::NewLine + + "}" + [System.Environment]::NewLine + + "}"; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable "apt-config" { + return "something"; + } + #act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = $null; + Set-AptProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + Assert-MockCalled "apt-config" -Times 1 -Exactly -ParameterFilter {$Args[0] -eq "dump" -and $Args[1] -eq "Acquire::http::proxy"}; + Assert-MockCalled Get-Content -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + $resultAptConf = [System.Environment]::NewLine + + "Acquire {" + [System.Environment]::NewLine + + "http {" + [System.Environment]::NewLine + + [System.Environment]::NewLine + + "}" + [System.Environment]::NewLine + + "}"; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Value -eq $resultAptConf}; + } + It("config exsists and isn't empty and a proxy is required, reset the proxy settings."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Get-Content { + return "Acquire::http::Proxy ""http://old.proxy:80"";" + [System.Environment]::NewLine + + "Acquire {" + [System.Environment]::NewLine + + "http {" + [System.Environment]::NewLine + + "proxy ""http://old.proxy:80"";" + [System.Environment]::NewLine + + "}" + [System.Environment]::NewLine + + "}"; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable "apt-config" { + return "something"; + } + #act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + Set-AptProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + Assert-MockCalled "apt-config" -Times 1 -Exactly -ParameterFilter {$Args[0] -eq "dump" -and $Args[1] -eq "Acquire::http::proxy"}; + Assert-MockCalled Get-Content -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + $resultAptConf = "Acquire::http::Proxy ""http://proxy.codez.one:8080"";" + [System.Environment]::NewLine + + "Acquire {" + [System.Environment]::NewLine + + "http {" + [System.Environment]::NewLine + + "proxy ""http://proxy.codez.one:8080"";" + [System.Environment]::NewLine + + "}" + [System.Environment]::NewLine + + "}"; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Value -eq $resultAptConf}; + } + It("user aren't root, but know it, do nothing."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + throw [System.UnauthorizedAccessException] "Your are not root"; + return $true; + } + Mock -Verifiable Get-Content { + return "Acquire::http::Proxy ""http://old.proxy:80"";" + [System.Environment]::NewLine + + "Acquire {" + [System.Environment]::NewLine + + "http {" + [System.Environment]::NewLine + + "proxy ""http://old.proxy:80"";" + [System.Environment]::NewLine + + "}" + [System.Environment]::NewLine + + "}"; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable "apt-config" { + return "something"; + } + #act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + Set-AptProxyConfiguration -Settings $settings -NoRoot; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + } + It("user aren't root, but don't know it, show an error."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + throw [System.UnauthorizedAccessException] "Your are not root"; + return $true; + } + Mock -Verifiable Get-Content { + return "Acquire::http::Proxy ""http://old.proxy:80"";" + [System.Environment]::NewLine + + "Acquire {" + [System.Environment]::NewLine + + "http {" + [System.Environment]::NewLine + + "proxy ""http://old.proxy:80"";" + [System.Environment]::NewLine + + "}" + [System.Environment]::NewLine + + "}"; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable "apt-config" { + return "something"; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + + #act & assert + {Set-AptProxyConfiguration -Settings $settings} | Should -Throw "You must be root to change APT settings."; + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/apt/apt.conf"}; + } + } + } + Describe "the docker function" { + Context "When Set-DockerProxyConfiguration is okay and" { + It("'docker' is undefined, it shouldn't throw an error"){ + # arrage + Mock -Verifiable Get-Command { + Write-Error "not found"; + } + #act + Set-DockerProxyConfiguration -Settings $null; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "docker"}; + } + It("no config exsists and no proxy are required, do nothing."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable Set-Content { + return; + } + #act + Set-DockerProxyConfiguration -Settings $null; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json"}; + Assert-MockCalled Set-Content -Times 0 -Exactly; + } + It("no config exsists and a proxy is required, write the config."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable New-Item{ + return; + } + #act + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + Set-DockerProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json"}; + Assert-MockCalled New-Item -Times 1 -Exactly -ParameterFilter {$ItemType -eq "Directory"}; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json" -and ($Value | ConvertFrom-Json).proxies.default.httpProxy -eq $settings.ProxyAddress -and ($Value | ConvertFrom-Json).proxies.default.httpsProxy -eq $settings.ProxyAddress -and ($Value | ConvertFrom-Json).proxies.default.noProxy -eq ($settings.BypassList -join ',')}; + } + It("config exsists and no proxy is required, reset proxy settings."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable New-Item{ + return; + } + Mock -Verifiable Get-Content{ + return '{ + "someProp": "someValue", + "proxies": + { + "default": + { + "httpProxy": "http://old.proxy:80", + "httpsProxy": "http://old.proxy:80", + "noProxy": "old, older" + } + } + }' + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = $null; + #act + Set-DockerProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json"}; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json" -and ($Value | ConvertFrom-Json).PsObject.Properties.name -notmatch "proxies" -and ($Value | ConvertFrom-Json).someProp -eq "someValue"}; + } + It("config exsists without proxy config and a proxy is required, set proxy settings."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable New-Item{ + return; + } + Mock -Verifiable Get-Content{ + return '{ + "someProp": "someValue" + }' + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + #act + Set-DockerProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json"}; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json" -and ($Value | ConvertFrom-Json).proxies.default.httpProxy -eq $settings.ProxyAddress -and ($Value | ConvertFrom-Json).proxies.default.httpsProxy -eq $settings.ProxyAddress -and ($Value | ConvertFrom-Json).proxies.default.noProxy -eq ($settings.BypassList -join ',') -and ($Value | ConvertFrom-Json).someProp -eq "someValue"}; + } + It("config exsists with proxy config but without default config and a proxy is required, reset proxy settings."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable New-Item{ + return; + } + Mock -Verifiable Get-Content{ + return '{ + "someProp": "someValue", + "proxies": + { + "def": + { + "httpProxy": "http://old.proxy:80", + "httpsProxy": "http://old.proxy:80", + "noProxy": "old, older" + } + } + }' + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + #act + Set-DockerProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json"}; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json" -and ($Value | ConvertFrom-Json).proxies.default.httpProxy -eq $settings.ProxyAddress -and ($Value | ConvertFrom-Json).proxies.default.httpsProxy -eq $settings.ProxyAddress -and ($Value | ConvertFrom-Json).proxies.default.noProxy -eq ($settings.BypassList -join ',') -and ($Value | ConvertFrom-Json).someProp -eq "someValue"}; + } + It("config exsists with proxy config and a proxy is required, reset proxy settings."){ + # arrage + Mock -Verifiable Get-Command { + return "not null"; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Set-Content { + return; + } + Mock -Verifiable New-Item{ + return; + } + Mock -Verifiable Get-Content{ + return '{ + "someProp": "someValue", + "proxies": + { + "default": + { + "httpProxy": "http://old.proxy:80", + "httpsProxy": "http://old.proxy:80", + "noProxy": "old, older" + } + } + }' + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + #act + Set-DockerProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly; + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json"}; + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Path -eq "~/.docker/config.json" -and ($Value | ConvertFrom-Json).proxies.default.httpProxy -eq $settings.ProxyAddress -and ($Value | ConvertFrom-Json).proxies.default.httpsProxy -eq $settings.ProxyAddress -and ($Value | ConvertFrom-Json).proxies.default.noProxy -eq ($settings.BypassList -join ',') -and ($Value | ConvertFrom-Json).someProp -eq "someValue"}; + } + } + } + Describe "the powershell function" { + Context "When Set-PowerShellProxyConfiguration is okay and" -Skip:($skipBecauseWindows){ + It("user aren't root, but know it, do nothing."){ + # arrage + Mock -Verifiable Get-Command { + } + Mock -Verifiable Test-Path { + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + #act + Set-PowerShellProxyConfiguration -Settings $settings -NoRoot; + # assert + Assert-MockCalled Get-Command -Times 0 -Exactly; + Assert-MockCalled Test-Path -Times 0 -Exactly; + } + It("'pwsh' and 'powershell' isn't there, do nothing."){ + # arrage + Mock -Verifiable Get-Command { + Write-Error "not found"; + } + Mock -Verifiable Test-Path { + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 0 -Exactly; + } + It("no config exsists and no proxy are required, do nothing."){ + # arrage + Mock -Verifiable Get-Command { + return [pscustomobject]@{Path = "something"}; + } + Mock -Verifiable Test-Path { + return $false; + } + $settings = [ProxySetting](New-Object ProxySetting); + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 2 -Exactly -ParameterFilter {$Path -eq "something.config"}; + } + It("no config exsists and a proxy is required, write the config."){ + # arrage + Mock -Verifiable Get-Command { + return [pscustomobject]@{Path = "something"}; + } + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable New-Item { + return; + } + Mock -Verifiable Get-Content { + return $null; + } + Mock -Verifiable Set-Content { + return ""; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 4 -Exactly -ParameterFilter {$Path -eq "something.config"}; + Assert-MockCalled New-Item -Times 2 -Exactly -ParameterFilter {$Path -eq "something.config" -and $ItemType -eq "File"}; + Assert-MockCalled Get-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "something.config"}; + Assert-MockCalled Set-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "something.config" -and ([xml]$Value).configuration["system.net"].defaultProxy.proxy.proxyaddress -eq $settings.ProxyAddress -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist -eq $null}; + + } + It("a proxy and a bypasslist is required, write both to the config."){ + # arrage + Mock -Verifiable Get-Command { + return [pscustomobject]@{Path = "something"}; + } + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable New-Item { + return; + } + Mock -Verifiable Get-Content { + return $null; + } + Mock -Verifiable Set-Content { + return ""; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 4 -Exactly -ParameterFilter {$Path -eq "something.config"}; + Assert-MockCalled New-Item -Times 2 -Exactly -ParameterFilter {$Path -eq "something.config" -and $ItemType -eq "File"}; + Assert-MockCalled Get-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "something.config"}; + Assert-MockCalled Set-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "something.config" -and ([xml]$Value).configuration["system.net"].defaultProxy.proxy.proxyaddress -eq $settings.ProxyAddress -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[0].address -eq $settings.BypassList[0] -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[1].address -eq $settings.BypassList[1]}; + } + It("config is already exsists but is empty a proxy and a bypasslist is required, write both to the config"){ + # arrage + Mock -Verifiable Get-Command { + # use testdrive here, because the XML function save will use it. + return [pscustomobject]@{Path = "$TestDrive/something"}; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable New-Item { + return; + } + Mock -Verifiable Get-Content { + return ''; + } + Mock -Verifiable Set-Content { + return ""; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled New-Item -Times 0 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and $ItemType -eq "File"}; + Assert-MockCalled Get-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled Set-Content -Times 0 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and ([xml]$Value).configuration["system.net"].defaultProxy.proxy.proxyaddress -eq $settings.ProxyAddress -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[0].address -eq $settings.BypassList[0] -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[1].address -eq $settings.BypassList[1]}; + } + It("config is already used a proxy and a bypasslist is required, write both to the config, without destroying exsisting configuration."){ + # arrage + Mock -Verifiable Get-Command { + # use testdrive here, because the XML function save will use it. + return [pscustomobject]@{Path = "$TestDrive/something"}; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable New-Item { + return; + } + Mock -Verifiable Get-Content { + return ' + testvalue + '; + } + Mock -Verifiable Set-Content { + return ""; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled New-Item -Times 0 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and $ItemType -eq "File"}; + Assert-MockCalled Get-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled Set-Content -Times 0 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and ([xml]$Value).configuration["system.net"].defaultProxy.proxy.proxyaddress -eq $settings.ProxyAddress -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[0].address -eq $settings.BypassList[0] -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[1].address -eq $settings.BypassList[1]}; + ([xml](Get-Content TestDrive:/something.config)).configuration.someconfig | Should -Be "testvalue"; + } + It("config is already used a proxy and a bypasslist is required, write both to the config, without destroying exsisting configuration.system.net."){ + # arrage + Mock -Verifiable Get-Command { + # use testdrive here, because the XML function save will use it. + return [pscustomobject]@{Path = "$TestDrive/something"}; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable New-Item { + return; + } + Mock -Verifiable Get-Content { + return ' + + testvalue + + '; + } + Mock -Verifiable Set-Content { + return ""; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled New-Item -Times 0 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and $ItemType -eq "File"}; + Assert-MockCalled Get-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled Set-Content -Times 0 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and ([xml]$Value).configuration["system.net"].defaultProxy.proxy.proxyaddress -eq $settings.ProxyAddress -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[0].address -eq $settings.BypassList[0] -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[1].address -eq $settings.BypassList[1]}; + ([xml](Get-Content TestDrive:/something.config)).configuration["system.net"].someconfig | Should -Be "testvalue"; + } + It("config had alread proxy, but enother proxy and bypasslist is required, write both to the config, and remove the old one"){ + # arrage + Mock -Verifiable Get-Command { + # use testdrive here, because the XML function save will use it. + return [pscustomobject]@{Path = "$TestDrive/something"}; + } + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable New-Item { + return; + } + Mock -Verifiable Get-Content { + return ' + + + + + + + + + '; + } + Mock -Verifiable Set-Content { + return ""; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + $settings.BypassList = "*.codez.one", "codez.one"; + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled New-Item -Times 0 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and $ItemType -eq "File"}; + Assert-MockCalled Get-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled Set-Content -Times 0 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and ([xml]$Value).configuration["system.net"].defaultProxy.proxy.proxyaddress -eq $settings.ProxyAddress -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[0].address -eq $settings.BypassList[0] -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist.add[1].address -eq $settings.BypassList[1]}; + } + } + Context "When Set-PowerShellProxyConfiguration is running in Windows and" -Skip:($skipBecauseLinux) { + It("no config exsists and a proxy is required, write the config."){ + # arrage + $defaultAcl = (New-Object System.Security.AccessControl.DirectorySecurity); + Mock -Verifiable Get-Command { + return [pscustomobject]@{Path = "$TestDrive/something"}; + } + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable New-Item { + return; + } + Mock -Verifiable Get-Item { + return ([pscustomobject]@{ + Directory = [pscustomobject]@{ + FullName = "$TestDrive" + } + }); + } + Mock -Verifiable Get-Content { + return $null; + } + Mock -Verifiable Set-Content { + return ""; + } + Mock -Verifiable Get-Acl { + return $defaultAcl; + } + Mock -Verifiable Set-Acl { + return; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + #act + Set-PowerShellProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "pwsh"}; + Assert-MockCalled Get-Command -Times 1 -Exactly -ParameterFilter {$Name -eq "powershell"}; + Assert-MockCalled Test-Path -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled New-Item -Times 2 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and $ItemType -eq "File"}; + Assert-MockCalled Get-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config"}; + Assert-MockCalled Set-Content -Times 2 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and ([xml]$Value).configuration["system.net"].defaultProxy.proxy.proxyaddress -eq $settings.ProxyAddress -and ([xml]$Value).configuration["system.net"].defaultProxy.bypasslist -eq $null}; + + ## make sure to set and reset folder acl + Assert-MockCalled Set-Acl -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive" -and $AclObject.Access.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value -eq "S-1-5-32-544" -and $AclObject.Access.AccessControlType -eq "Allow"}; + Assert-MockCalled Set-Acl -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive" -and $AclObject -eq $defaultAcl}; + + ## make sure to set and reset file acl + Assert-MockCalled Set-Acl -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and $AclObject.Access.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value -eq "S-1-5-32-544" -and $AclObject.Access.AccessControlType -eq "Allow"}; + Assert-MockCalled Set-Acl -Times 4 -Exactly -ParameterFilter {$Path -eq "$TestDrive/something.config" -and $AclObject -eq $defaultAcl}; + } + } + } + Describe "the environment function" { + Context "When Set-EnvironmentProxyConfiguration is okay and" -Skip:($skipBecauseWindows){ + It("user aren't root, but know it, do nothing."){ + # arrage + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + #act + Set-EnvironmentProxyConfiguration -Settings $settings -NoRoot -WarningVariable warning; + # assert + $warning | Should -Be "Currently to set the environment this script needs root rights. Didn't change any environment varables."; + } + It("no config exsists and no proxy are required, do nothing."){ + # arrage + Mock -Verifiable Test-Path { + return $false; + } + Mock -Verifiable Remove-Item { + return $false; + } + $settings = [ProxySetting](New-Object ProxySetting); + #act + Set-EnvironmentProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/profile.d/proxy.sh"}; + Assert-MockCalled Remove-Item -Times 0 -Exactly -ParameterFilter {$Path -eq "/etc/profile.d/proxy.sh"}; + } + It("a proxy is required, write the config."){ + # arrage + Mock -Verifiable Set-Content { + return ; + } + $settings = [ProxySetting](New-Object ProxySetting); + $settings.ProxyAddress = "http://proxy.codez.one:8080"; + #act + Write-Warning "start"; + Set-EnvironmentProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Set-Content -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/profile.d/proxy.sh" -and ([string]$Value).Contains("export http_proxy=$($settings.ProxyAddress)") -and ([string]$Value).Contains("export https_proxy=$($settings.ProxyAddress)") -and ([string]$Value).Contains("export no_proxy=$($Settings.BypassList -join ',')") -and ([string]$Value).Contains("export HTTPS_PROXY=$($settings.ProxyAddress)") -and ([string]$Value).Contains("export HTTP_PROXY=$($settings.ProxyAddress)")}; + } + It("no proxy is required but config exsists, remove it."){ + # arrage + Mock -Verifiable Test-Path { + return $true; + } + Mock -Verifiable Remove-Item { + return; + } + $settings = [ProxySetting](New-Object ProxySetting); + #act + Set-EnvironmentProxyConfiguration -Settings $settings; + # assert + Assert-MockCalled Test-Path -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/profile.d/proxy.sh"}; + Assert-MockCalled Remove-Item -Times 1 -Exactly -ParameterFilter {$Path -eq "/etc/profile.d/proxy.sh"}; + } + } + Context "When Set-PowerShellProxyConfiguration is running in Windows and" -Skip:($skipBecauseLinux) { + # TODO: Can't test static dotnet calls. Needs a solution for this. + } + } +} \ No newline at end of file diff --git a/tests/Test-ProxyConfiguration.tests.ps1 b/tests/Test-ProxyConfiguration.tests.ps1 index e04a45d..a883809 100644 --- a/tests/Test-ProxyConfiguration.tests.ps1 +++ b/tests/Test-ProxyConfiguration.tests.ps1 @@ -1,9 +1,13 @@ -Describe "Test-ProxyConfiguration" { +$skipBecauseLinux = ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) -eq $false; +$skipBecauseWindows = ($PSVersionTable.PSEdition -eq "Desktop" -or $IsWindows) -eq $true; +Describe "Test-ProxyConfiguration" -Skip:($skipBecauseLinux) { BeforeAll { - $fileInfo = Get-ChildItem $PSScriptRoot; + $fileInfo = Get-ChildItem $PSCommandPath; $functionName = $fileInfo.Name.Split('.')[0]; + $file = Get-ChildItem "$PSScriptRoot/../src/$functionName.ps1"; + $targetFileName = "$($file.FullName)"; # load function to test - . "$PSScriptRoot/../src/$functionName.ps1"; + . "$targetFileName"; } Context "When Test-Connection is okay and" { BeforeEach { @@ -157,12 +161,14 @@ Describe "Test-ProxyConfiguration" { } } -Describe "ProxyTestResult" { +Describe "ProxyTestResult" -Skip:($skipBecauseLinux) { BeforeAll { - $fileInfo = Get-ChildItem $PSScriptRoot; + $fileInfo = Get-ChildItem $PSCommandPath; $functionName = $fileInfo.Name.Split('.')[0]; + $file = Get-ChildItem "$PSScriptRoot/../src/$functionName.ps1"; + $targetFileName = "$($file.FullName)"; # load function to test - . "$PSScriptRoot/../src/$functionName.ps1"; + . "$targetFileName"; } Context 'everthing is perfect' { It 'It should print a good message, if the bypass list is used correct.' {