Adds support for handling authentication requests with basic auth

This commit is contained in:
Lord Hepipud 2020-05-29 18:02:30 +02:00
parent 6838933bd5
commit 73fe3aac31
4 changed files with 240 additions and 0 deletions

View file

@ -25,6 +25,36 @@
'Details' = 'A client connection was terminated by the Framework because no secure SSL handshake could be established. This issue in general is followed by EventId 1500.';
'EventId' = 1501;
};
1550 = @{
'EntryType' = 'Error';
'Message' = 'Unsupported web authentication used';
'Details' = 'A web client tried to authenticate with an unsupported authorization method.';
'EventId' = 1550;
};
1551 = @{
'EntryType' = 'Warning';
'Message' = 'Invalid authentication credentials provided';
'Details' = 'A web request for a client was rejected because of invalid formated base64 encoded credentials.';
'EventId' = 1551;
};
1552 = @{
'EntryType' = 'Error';
'Message' = 'Failed to parse use credentials from base64 encoding';
'Details' = 'Provided user credentials encoded as base64 could not be converted to domain, user and password objects.';
'EventId' = 1552;
};
1560 = @{
'EntryType' = 'Error';
'Message' = 'Failed to test user login as no Principal Context could be established';
'Details' = 'A web client trying to authenticate failed as no Principal Context for the provided domain could be established.';
'EventId' = 1560;
};
1561 = @{
'EntryType' = 'Error';
'Message' = 'Failed to authenticate user with given credentials';
'Details' = 'A web client trying to authenticate failed as the provided user credentials could not be verified.';
'EventId' = 1561;
};
}
};

View file

@ -0,0 +1,102 @@
<#
.SYNOPSIS
Converts a provided Authorization header to credentials
.DESCRIPTION
Converts a provided Authorization header to credentials
.FUNCTIONALITY
Converts a provided Authorization header to credentials
.EXAMPLE
PS>Convert-Base64ToCredentials -AuthString "Basic =Bwebb474567b56756b...";
.PARAMETER AuthString
The value of the Authorization header of the web request
.INPUTS
System.String
.OUTPUTS
System.Hashtable
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Convert-Base64ToCredentials()
{
param (
[String]$AuthString
);
[hashtable]$Credentials = @{};
$AuthArray = $AuthString.Split(' ');
switch ($AuthArray[0]) {
'Basic' {
$AuthString = $AuthArray[1];
};
default {
Write-IcingaEventMessage -EventId 1550 -Namespace 'Framework' -Objects $AuthArray[0];
return @{};
}
}
# Convert the Base64 Secure String back to a normal string
[string]$AuthString = [System.Text.Encoding]::UTF8.GetString(
[System.Convert]::FromBase64String(
$AuthString
)
);
# If no ':' is within the string, the credential data is not properly formated
if ($AuthString.Contains(':') -eq $FALSE) {
Write-IcingaEventMessage -EventId 1551 -Namespace 'Framework';
$AuthString = $null;
return $Credentials;
}
try {
# Build our User Data and Password from the string
[string]$UserData = $AuthString.Substring(
0,
$AuthString.IndexOf(':')
);
$Credentials.Add(
'password',
(ConvertTo-IcingaSecureString `
$AuthString.Substring(
$AuthString.IndexOf(':') + 1,
$AuthString.Length - $UserData.Length - 1
)
)
);
$AuthString = $null;
# Extract a possible domain
if ($UserData.Contains('\')) {
# Split the auth string on the '\'
[array]$AuthData = $UserData.Split('\');
# First value of the array is the Domain, second is the Username
$Credentials.Add('domain', $AuthData[0]);
$Credentials.Add(
'user',
(ConvertTo-IcingaSecureString `
$AuthData[1]
)
);
$AuthData = $null;
} else {
$Credentials.Add('domain', $null);
$Credentials.Add(
'user',
(ConvertTo-IcingaSecureString `
$UserData
)
);
}
$UserData = $null;
} catch {
Write-IcingaEventMessage -EventId 1552 -Namespace 'Framework' -Objects $_.Exception;
return @{};
}
return $Credentials;
}

View file

@ -0,0 +1,32 @@
<#
.SYNOPSIS
Sends a basic auth request back to the client
.DESCRIPTION
Sends a basic auth request back to the client
.FUNCTIONALITY
Sends a basic auth request back to the client
.EXAMPLE
PS>Send-IcingaWebAuthMessage -Connection $Connection;
.PARAMETER Connection
The connection data of the Framework containing the client and stream object
.INPUTS
System.Hashtable
.OUTPUTS
Null
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Send-IcingaWebAuthMessage()
{
param (
[Hashtable]$Connection = @{}
);
Send-IcingaTCPClientMessage -Message (
New-IcingaTCPClientRESTMessage `
-HTTPResponse ($IcingaHTTPEnums.HTTPResponseType.Unauthorized) `
-ContentBody 'Please provide your credentials for login.' `
-BasicAuth
) -Stream $Connection.Stream;
}

View file

@ -0,0 +1,76 @@
<#
.SYNOPSIS
Tests provided credentials against either the local machine or a domain controller
.DESCRIPTION
Tests provided credentials against either the local machine or a domain controller
.FUNCTIONALITY
Tests provided credentials against either the local machine or a domain controller
.EXAMPLE
PS>Test-IcingaRESTCredentials $UserName $SecureUser -Password $SecurePassword;
.EXAMPLE
PS>Test-IcingaRESTCredentials $UserName $SecureUser -Password $SecurePassword -Domain 'Example';
.PARAMETER UserName
The username to use for login as SecureString
.PARAMETER Password
The password to use for login as SecureString
.PARAMETER Domain
The domain to use for login as string
.INPUTS
System.SecureString
.OUTPUTS
System.Boolean
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Test-IcingaRESTCredentials()
{
param (
[SecureString]$UserName,
[SecureString]$Password,
[String]$Domain
);
Add-Type -AssemblyName System.DirectoryServices.AccountManagement;
# Base handling: We try to authenticate against a local user on the machine
[string]$AuthMethod = [System.DirectoryServices.AccountManagement.ContextType]::Machine;
[string]$AuthDomain = $env:COMPUTERNAME;
# If we specify a domain, we should authenticate against our Domain
if ([string]::IsNullOrEmpty($Domain) -eq $FALSE) {
$AuthMethod = [System.DirectoryServices.AccountManagement.ContextType]::Domain;
$AuthDomain = $Domain;
}
try {
# Create an Account Management object based on the above determined settings
$AccountService = New-Object System.DirectoryServices.AccountManagement.PrincipalContext(
$AuthMethod,
$AuthDomain
);
} catch {
# Regardless of the error, print the message and return false to prevent further execution
Write-IcingaEventMessage -EventId 1560 -Namespace 'Framework' -Objects $_.Exception;
return $FALSE;
}
# In case we couldn't setup the Account Service, always return false
if ($null -eq $AccountService) {
return $FALSE;
}
try {
# Try to authenticate and either return true or false as integer
[bool]$AuthResult = [int]($AccountService.ValidateCredentials(
(ConvertFrom-IcingaSecureString $UserName),
(ConvertFrom-IcingaSecureString $Password)
));
return $AuthResult;
} catch {
Write-IcingaEventMessage -EventId 1561 -Namespace 'Framework' -Objects $_.Exception;
}
return $FALSE;
}