Merge pull request #157 from Icinga/feature/Feature-Requests-Add-Proxy-Server-support

Feature: Add Proxy Server support for web calls

Also re-arranges web content by using old content from lib/web into lib/webserver, while new lib/web contains the proxy configuration.
This commit is contained in:
Lord Hepipud 2020-11-19 17:22:37 +01:00 committed by GitHub
commit 3ec7559d12
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 262 additions and 19 deletions

View file

@ -5,6 +5,7 @@ The Icinga PowerShell Framework ships with a bunch of Cmdlets for monitoring, me
## Framework Management ## Framework Management
* [Automated Framework and Component deployment](frameworkusage/01-Automated-Framework-and-Component-Deployment.md) * [Automated Framework and Component deployment](frameworkusage/01-Automated-Framework-and-Component-Deployment.md)
* [Enable Proxy Server](frameworkusage/02-Enable-Proxy-Server.md)
## Icinga Agent Management ## Icinga Agent Management

View file

@ -13,6 +13,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
### Enhancements ### Enhancements
* [#19](https://github.com/Icinga/icinga-powershell-framework/issues/19) Add support for proxy servers for web calls and re-arranges content from lib/web to lib/webserver and uses lib/web for new proxy/web calls
* [#121](https://github.com/Icinga/icinga-powershell-framework/issues/121) Adds feature allowing sharing of local variables with Icinga Shell, by using `-ArgumentList`. They can then be accessed by using `$IcingaShellArgs` with the correct array index id, following the order of items added to `-ArgumentList` * [#121](https://github.com/Icinga/icinga-powershell-framework/issues/121) Adds feature allowing sharing of local variables with Icinga Shell, by using `-ArgumentList`. They can then be accessed by using `$IcingaShellArgs` with the correct array index id, following the order of items added to `-ArgumentList`
* [#136](https://github.com/Icinga/icinga-powershell-framework/pull/136) Adds support to ignore empty check packages and return `Ok` instead of `Unknown` if `-IgnoreEmptyPackage` is set on `New-IcingaCheckPackage` * [#136](https://github.com/Icinga/icinga-powershell-framework/pull/136) Adds support to ignore empty check packages and return `Ok` instead of `Unknown` if `-IgnoreEmptyPackage` is set on `New-IcingaCheckPackage`
* [#137](https://github.com/Icinga/icinga-powershell-framework/issues/137) Adds Cmdlet to compare a DateTime object with the current DateTime and return the offset as Integer in seconds * [#137](https://github.com/Icinga/icinga-powershell-framework/issues/137) Adds Cmdlet to compare a DateTime object with the current DateTime and return the offset as Integer in seconds

View file

@ -0,0 +1,23 @@
# Enable Proxy Server
With Icinga PowerShell Framework v1.3.0 we added support for using Proxy servers while using web requests to download and fetch information. For this we added a custom function `Invoke-IcingaWebRequest` as wrapper function for `Invoke-WebRequest`.
## Enable Proxy Server Support
To enable the proxy server support, you simply have to use the Cmdlet `Set-IcingaFrameworkProxyServer` and set your proxy server:
```powershell
Set-IcingaFrameworkProxyServer -Server 'http://example.com:8080';
```
Once set, the Framework will automatically use this server configuration for all web requests.
## Disable Proxy Server Support
To disable the proxy server, you can use the same Cmdlet again, but leaving the argument empty.
```powershell
Set-IcingaFrameworkProxyServer;
```
Now all web requests are executed without the proxy server.

View file

@ -42,7 +42,7 @@ function Get-IcingaDirectorSelfServiceConfig()
$EndpointUrl = Join-WebPath -Path $DirectorUrl -ChildPath ([string]::Format('/self-service/powershell-parameters?key={0}', $ApiKey)); $EndpointUrl = Join-WebPath -Path $DirectorUrl -ChildPath ([string]::Format('/self-service/powershell-parameters?key={0}', $ApiKey));
$response = Invoke-WebRequest -Uri $EndpointUrl -UseBasicParsing -Headers @{ 'accept' = 'application/json'; 'X-Director-Accept' = 'application/json' } -Method 'POST'; $response = Invoke-IcingaWebRequest -Uri $EndpointUrl -UseBasicParsing -Headers @{ 'accept' = 'application/json'; 'X-Director-Accept' = 'application/json' } -Method 'POST';
if ($response.StatusCode -ne 200) { if ($response.StatusCode -ne 200) {
throw $response.Content; throw $response.Content;

View file

@ -42,7 +42,7 @@ function Get-IcingaDirectorSelfServiceTicket()
[string]$url = Join-WebPath -Path $DirectorUrl -ChildPath ([string]::Format('/self-service/ticket?key={0}', $ApiKey)); [string]$url = Join-WebPath -Path $DirectorUrl -ChildPath ([string]::Format('/self-service/ticket?key={0}', $ApiKey));
$response = Invoke-WebRequest -Uri $url -UseBasicParsing -Headers @{ 'accept' = 'application/json'; 'X-Director-Accept' = 'application/json' } -Method 'POST'; $response = Invoke-IcingaWebRequest -Uri $url -UseBasicParsing -Headers @{ 'accept' = 'application/json'; 'X-Director-Accept' = 'application/json' } -Method 'POST';
if ($response.StatusCode -ne 200) { if ($response.StatusCode -ne 200) {
throw $response.Content; throw $response.Content;

View file

@ -60,7 +60,7 @@ function Register-IcingaDirectorSelfServiceHost()
$EndpointUrl = Join-WebPath -Path $DirectorUrl -ChildPath ([string]::Format('/self-service/register-host?name={0}&key={1}', $Hostname, $ApiKey)); $EndpointUrl = Join-WebPath -Path $DirectorUrl -ChildPath ([string]::Format('/self-service/register-host?name={0}&key={1}', $Hostname, $ApiKey));
$response = Invoke-WebRequest -Uri $EndpointUrl -UseBasicParsing -Headers @{ 'accept' = 'application/json'; 'X-Director-Accept' = 'application/json' } -Method 'POST' -Body $DirectorConfigJson; $response = Invoke-IcingaWebRequest -Uri $EndpointUrl -UseBasicParsing -Headers @{ 'accept' = 'application/json'; 'X-Director-Accept' = 'application/json' } -Method 'POST' -Body $DirectorConfigJson;
if ($response.StatusCode -ne 200) { if ($response.StatusCode -ne 200) {
throw $response.Content; throw $response.Content;

View file

@ -36,7 +36,7 @@ function Get-IcingaFrameworkServiceBinary()
if ([string]::IsNullOrEmpty($FrameworkServiceUrl)) { if ([string]::IsNullOrEmpty($FrameworkServiceUrl)) {
if ((Get-IcingaAgentInstallerAnswerInput -Prompt 'Do you provide a custom source of the service binary?' -Default 'n').result -eq 1) { if ((Get-IcingaAgentInstallerAnswerInput -Prompt 'Do you provide a custom source of the service binary?' -Default 'n').result -eq 1) {
$LatestRelease = (Invoke-WebRequest -Uri 'https://github.com/Icinga/icinga-powershell-service/releases/latest' -UseBasicParsing).BaseResponse.ResponseUri.AbsoluteUri; $LatestRelease = (Invoke-IcingaWebRequest -Uri 'https://github.com/Icinga/icinga-powershell-service/releases/latest' -UseBasicParsing).BaseResponse.ResponseUri.AbsoluteUri;
$FrameworkServiceUrl = $LatestRelease.Replace('/tag/', '/download/'); $FrameworkServiceUrl = $LatestRelease.Replace('/tag/', '/download/');
$Tag = $FrameworkServiceUrl.Split('/')[-1]; $Tag = $FrameworkServiceUrl.Split('/')[-1];
$FrameworkServiceUrl = [string]::Format('{0}/icinga-service-{1}.zip', $FrameworkServiceUrl, $Tag); $FrameworkServiceUrl = [string]::Format('{0}/icinga-service-{1}.zip', $FrameworkServiceUrl, $Tag);
@ -64,9 +64,7 @@ function Get-IcingaFrameworkServiceBinary()
$UpdateBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe.update'; $UpdateBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe.update';
$ServiceBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe'; $ServiceBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe';
try { if ((Invoke-IcingaWebRequest -Uri $FrameworkServiceUrl -UseBasicParsing -OutFile $ZipArchive).HasErrors) {
Invoke-WebRequest -Uri $FrameworkServiceUrl -UseBasicParsing -OutFile $ZipArchive;
} catch {
Write-IcingaConsoleError -Message 'Failed to download the Icinga Service Binary from "{0}". Please try again.' -Objects $FrameworkServiceUrl; Write-IcingaConsoleError -Message 'Failed to download the Icinga Service Binary from "{0}". Please try again.' -Objects $FrameworkServiceUrl;
return Get-IcingaFrameworkServiceBinary; return Get-IcingaFrameworkServiceBinary;
} }

View file

@ -70,11 +70,13 @@ function Get-IcingaPowerShellModuleArchive()
if ($branch.ToLower() -eq 'snapshot') { if ($branch.ToLower() -eq 'snapshot') {
$DownloadUrl = [string]::Format('https://github.com/{0}/{1}/archive/master.zip', $GitHubUser, $Repository); $DownloadUrl = [string]::Format('https://github.com/{0}/{1}/archive/master.zip', $GitHubUser, $Repository);
} else { } else {
try { $WebResponse = Invoke-IcingaWebRequest -Uri 'https://github.com/{0}/{1}/releases/latest' -Objects $GitHubUser, $Repository -UseBasicParsing;
$LatestRelease = (Invoke-WebRequest -Uri ([string]::Format('https://github.com/{0}/{1}/releases/latest', $GitHubUser, $Repository)) -UseBasicParsing).BaseResponse.ResponseUri.AbsoluteUri;
if ($WebResponse.HasErrors -eq $FALSE) {
$LatestRelease = $WebResponse.BaseResponse.ResponseUri.AbsoluteUri;
$DownloadUrl = $LatestRelease.Replace('/releases/tag/', '/archive/'); $DownloadUrl = $LatestRelease.Replace('/releases/tag/', '/archive/');
$Tag = $DownloadUrl.Split('/')[-1]; $Tag = $DownloadUrl.Split('/')[-1];
} catch { } else {
Write-IcingaConsoleError -Message 'Failed to fetch latest release for "{0}" from GitHub. Either the module or the GitHub account do not exist' -Objects $ModuleName; Write-IcingaConsoleError -Message 'Failed to fetch latest release for "{0}" from GitHub. Either the module or the GitHub account do not exist' -Objects $ModuleName;
} }
@ -110,13 +112,11 @@ function Get-IcingaPowerShellModuleArchive()
}; };
} }
try {
$DownloadDirectory = New-IcingaTemporaryDirectory; $DownloadDirectory = New-IcingaTemporaryDirectory;
$DownloadDestination = (Join-Path -Path $DownloadDirectory -ChildPath ([string]::Format('{0}.zip', $Repository))); $DownloadDestination = (Join-Path -Path $DownloadDirectory -ChildPath ([string]::Format('{0}.zip', $Repository)));
Write-IcingaConsoleNotice ([string]::Format('Downloading "{0}" into "{1}"', $ModuleName, $DownloadDirectory)); Write-IcingaConsoleNotice ([string]::Format('Downloading "{0}" into "{1}"', $ModuleName, $DownloadDirectory));
Invoke-WebRequest -UseBasicParsing -Uri $DownloadUrl -OutFile $DownloadDestination; if ((Invoke-IcingaWebRequest -UseBasicParsing -Uri $DownloadUrl -OutFile $DownloadDestination).HasErrors) {
} catch {
Write-IcingaConsoleError ([string]::Format('Failed to download "{0}" into "{1}". Starting cleanup process', $ModuleName, $DownloadDirectory)); Write-IcingaConsoleError ([string]::Format('Failed to download "{0}" into "{1}". Starting cleanup process', $ModuleName, $DownloadDirectory));
Start-Sleep -Seconds 2; Start-Sleep -Seconds 2;
Remove-Item -Path $DownloadDirectory -Recurse -Force; Remove-Item -Path $DownloadDirectory -Recurse -Force;

View file

@ -21,7 +21,7 @@ function Get-IcingaAgentMSIPackage()
$LastUpdate = $null; $LastUpdate = $null;
if ($Version -eq 'snapshot' -Or $Version -eq 'release') { if ($Version -eq 'snapshot' -Or $Version -eq 'release') {
$Content = (Invoke-WebRequest -Uri $Source -UseBasicParsing).RawContent.Split("`r`n"); $Content = (Invoke-IcingaWebRequest -Uri $Source -UseBasicParsing).RawContent.Split("`r`n");
$UsePackage = $null; $UsePackage = $null;
foreach ($line in $Content) { foreach ($line in $Content) {
@ -62,7 +62,7 @@ function Get-IcingaAgentMSIPackage()
if ($SkipDownload -eq $FALSE) { if ($SkipDownload -eq $FALSE) {
$DownloadPath = Join-Path $Env:TEMP -ChildPath $UsePackage; $DownloadPath = Join-Path $Env:TEMP -ChildPath $UsePackage;
Write-IcingaConsoleNotice ([string]::Format('Downloading Icinga 2 Agent installer "{0}" into temp directory "{1}"', $UsePackage, $DownloadPath)); Write-IcingaConsoleNotice ([string]::Format('Downloading Icinga 2 Agent installer "{0}" into temp directory "{1}"', $UsePackage, $DownloadPath));
Invoke-WebRequest -Uri (Join-WebPath -Path $Source -ChildPath $UsePackage) -OutFile $DownloadPath; Invoke-IcingaWebRequest -Uri (Join-WebPath -Path $Source -ChildPath $UsePackage) -OutFile $DownloadPath;
} }
return @{ return @{

View file

@ -272,7 +272,7 @@ function Copy-IcingaAgentCACertificate()
Set-IcingaTLSVersion; Set-IcingaTLSVersion;
# It could also be a web ressource # It could also be a web ressource
try { try {
$response = Invoke-WebRequest $CAPath -UseBasicParsing; $response = Invoke-IcingaWebRequest $CAPath -UseBasicParsing;
[int]$Index = $response.RawContent.IndexOf("`r`n`r`n") + 4; [int]$Index = $response.RawContent.IndexOf("`r`n`r`n") + 4;
[string]$CAContent = $response.RawContent.SubString( [string]$CAContent = $response.RawContent.SubString(

View file

@ -0,0 +1,17 @@
<#
.SYNOPSIS
Disables the progress bar during file downloads or while loading certain modules.
This will increase the speed of certain tasks, for example file downloads
.DESCRIPTION
Disables the progress bar during file downloads or while loading certain modules.
This will increase the speed of certain tasks, for example file downloads
.FUNCTIONALITY
Sets the $ProgressPreference to 'SilentlyContinue'
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Disable-IcingaProgressPreference()
{
$global:ProgressPreference = "SilentlyContinue";
}

View file

@ -0,0 +1,18 @@
<#
.SYNOPSIS
Fetches the configuration of the configured Proxy server for the Framework, in
case it is set
.DESCRIPTION
etches the configuration of the configured Proxy server for the Framework, in
case it is set
.FUNCTIONALITY
etches the configuration of the configured Proxy server for the Framework, in
case it is set
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Get-IcingaFrameworkProxyServer()
{
return (Get-IcingaPowerShellConfig -Path 'Framework.Proxy.Server');
}

View file

@ -0,0 +1,144 @@
<#
.SYNOPSIS
A wrapper function for Invoke-WebRequest to allow easier proxy support and
to catch errors more directly.
.DESCRIPTION
A wrapper function for Invoke-WebRequest to allow easier proxy support and
to catch errors more directly.
.FUNCTIONALITY
Uses Invoke-WebRequest to fetch information and returns the same output, but
with direct error handling and global proxy support by configuration
.EXAMPLE
PS>Invoke-IcingaWebRequest -Uri 'https://icinga.com';
.EXAMPLE
PS>Invoke-IcingaWebRequest -Uri 'https://icinga.com' -UseBasicParsing;
.EXAMPLE
PS>Invoke-IcingaWebRequest -Uri 'https://{0}.com' -UseBasicParsing -Objects 'icinga';
.EXAMPLE
PS>Invoke-IcingaWebRequest -Uri 'https://{0}.com' -UseBasicParsing -Objects 'icinga' -Headers @{ 'accept' = 'application/json' };
.PARAMETER Uri
The Uri for the web request
.PARAMETER Body
Specifies the body of the request. The body is the content of the request that follows the headers. You can
also pipe a body value to Invoke-WebRequest.
The Body parameter can be used to specify a list of query parameters or specify the content of the response.
When the input is a GET request and the body is an IDictionary (typically, a hash table), the body is added
to the URI as query parameters. For other GET requests, the body is set as the value of the request body in
the standard name=value format.
When the body is a form, or it is the output of an Invoke-WebRequest call, Windows PowerShell sets the
request content to the form fields.
.PARAMETER Headers
Web headers send with the request as hashtable
.PARAMETER Method
The request method to send to the destination.
Allowed values: 'Get', 'Post', 'Put', 'Trace', 'Patch', 'Options', 'Merge', 'Head', 'Default', 'Delete'
.PARAMETER OutFile
Specifies the output file for which this cmdlet saves the response body. Enter a path and file name. If you omit the path, the default is the current location.
.PARAMETER UseBasicParsing
Indicates that the cmdlet uses the response object for HTML content without Document Object Model (DOM)
parsing.
This parameter is required when Internet Explorer is not installed on the computers, such as on a Server
Core installation of a Windows Server operating system.
.PARAMETER Objects
Use placeholders within the `-Uri` argument, like {0} and replace them with array elements of this argument.
The index entry of {0} has to match the order of this argument.
.INPUTS
System.String
.OUTPUTS
System.Boolean
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Invoke-IcingaWebRequest()
{
param (
[string]$Uri = '',
$Body,
[hashtable]$Headers,
[ValidateSet('Get', 'Post', 'Put', 'Trace', 'Patch', 'Options', 'Merge', 'Head', 'Default', 'Delete')]
[string]$Method = 'Get',
[string]$OutFile,
[switch]$UseBasicParsing,
[array]$Objects = @()
);
[int]$Index = 0;
foreach ($entry in $Objects) {
$Uri = $Uri.Replace(
[string]::Format('{0}{1}{2}', '{', $Index, '}'),
$entry
);
$Index++;
}
$WebArguments = @{
'Uri' = $Uri;
'Method' = $Method;
}
if ($Method -ne 'Get' -And $null -ne $Body -and [string]::IsNullOrEmpty($Body) -eq $FALSE) {
$WebArguments.Add('Body', $Body);
}
if ($Headers.Count -ne 0) {
$WebArguments.Add('Headers', $Headers);
}
if ([string]::IsNullOrEmpty($OutFile) -eq $FALSE) {
$WebArguments.Add('OutFile', $OutFile);
}
$ProxyServer = Get-IcingaFrameworkProxyServer;
if ([string]::IsNullOrEmpty($ProxyServer) -eq $FALSE) {
$WebArguments.Add('Proxy', $ProxyServer);
}
Set-IcingaTLSVersion;
Disable-IcingaProgressPreference;
try {
$Response = Invoke-WebRequest -UseBasicParsing:$UseBasicParsing @WebArguments -ErrorAction Stop;
} catch {
[string]$ErrorId = ([string]$_.FullyQualifiedErrorId).Split(',')[0];
[string]$Message = $_.Exception.Message;
switch ($ErrorId) {
'System.UriFormatException' {
Write-IcingaConsoleError 'The provided Url "{0}" is not a valid format' -Objects $Uri;
break;
};
'WebCmdletWebResponseException' {
Write-IcingaConsoleError 'The remote host for address "{0}" could not be resolved' -Objects $Uri;
break;
};
'System.InvalidOperationException' {
Write-IcingaConsoleError 'Failed to query host "{0}". Possible this is caused by an invalid Proxy Server configuration: "{1}".' -Objects $Uri, $ProxyServer;
break;
};
Default {
Write-IcingaConsoleError 'Unhandled exception for Url "{0}" with error id "{1}":{2}{2}{3}' -Objects $Uri, $ErrorId, (New-IcingaNewLine), $Message;
break;
};
}
# Return some sort of objects which are often used to ensure we at least have some out-of-the-box compatibility
return @{
'HasErrors' = $TRUE;
'BaseResponse' = @{
'ResponseUri' = @{
'AbsoluteUri' = $Uri;
};
};
'StatusCode' = 900;
};
}
return $Response;
}

View file

@ -0,0 +1,30 @@
<#
.SYNOPSIS
Sets the configuration for a proxy server which is used by all Invoke-WebRequests
to ensure internet connections are working correctly.
.DESCRIPTION
Sets the configuration for a proxy server which is used by all Invoke-WebRequests
to ensure internet connections are working correctly.
.FUNCTIONALITY
Sets the configuration for a proxy server which is used by all Invoke-WebRequests
to ensure internet connections are working correctly.
.EXAMPLE
PS>Set-IcingaFrameworkProxyServer -Server 'http://example.com:8080';
.PARAMETER Server
The server with the port for the Proxy. Example: 'http://example.com:8080'
.INPUTS
System.String
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Set-IcingaFrameworkProxyServer()
{
param (
[string]$Server = ''
);
Set-IcingaPowerShellConfig -Path 'Framework.Proxy.Server' -Value $Server;
Write-IcingaConsoleNotice 'The Proxy server for the PowerShell Framework has been set to "{0}"' -Objects $Server;
}

View file

@ -1,3 +1,14 @@
<#
.SYNOPSIS
Sets the allowed TLS version for communicating with endpoints to TLS 1.2 and 1.1
.DESCRIPTION
Sets the allowed TLS version for communicating with endpoints to TLS 1.2 and 1.1
.FUNCTIONALITY
Uses the [Net.ServicePointManager] to set the SecurityProtocol to TLS 1.2 and 1.1
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Set-IcingaTLSVersion() function Set-IcingaTLSVersion()
{ {
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11"; [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11";