Skip to content

Commit

Permalink
Merge pull request #76 from microsoft/users/menakakollu/sap-setup-ass…
Browse files Browse the repository at this point in the history
…istant-scripts-and-layered-solution

Added new scripts, .zip with powershell scripts. Added SAP drop down …
  • Loading branch information
menakakmsft authored Aug 22, 2024
2 parents 5519f09 + b20b65e commit 7719c33
Show file tree
Hide file tree
Showing 5 changed files with 387 additions and 0 deletions.
Binary file added Scripts/SAPSetupAssistantValidationScripts.zip
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<#
.SYNOPSIS
Checks for on-premises data gateway installation.
.DESCRIPTION
This script attempts to
1. Check if the on-premises data gateway is installed and validates the
if the version is greater than the minimum version requirement
2. CheckSapConnector
3. CheckVisualCPlusPlus
#>

$minimumVersion = "3000.150.11" # November 2022
$serviceName = "PBIEgwService"
$service = Get-Service $serviceName -ErrorAction SilentlyContinue

if ($service) {
$servicePath = (Get-WmiObject Win32_Service | Where-Object { $_.Name -eq $serviceName }).PathName
$exePath = $servicePath.Trim('"')
$versionInfo = (Get-Command $exePath).FileVersionInfo
$versionNumber = $versionInfo.ProductVersion

if ([version]$versionNumber -ge [version]$minimumVersion) {
Write-Host -NoNewLine "{'step': 'CheckGatewayVersion', 'status': 'Success', 'message': 'The on-premises data gateway is installed and version ($versionNumber) is greater than or equal to ($minimumVersion).'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckGatewayVersion', 'status': 'Error', 'message': 'Your on-premises data gateway doesn't meet the minimum version, please upgrade by downloading the latest version here: https://go.microsoft.com/fwlink/?linkid=2240537.'},"
}
}
else {
Write-Host -NoNewLine "{'step': 'CheckGatewayVersion', 'status': 'Error', 'message': 'The on-premises data gateway is not installed. Download it here: https://go.microsoft.com/fwlink/?linkid=2240537.'},"
}

# .NET SDK for SAP
$currentLocation = Get-Location
$location = "C:\Windows\Microsoft.NET\assembly"
$ncoAssemblies = Get-ChildItem -Path $location -Filter sapnco.dll -Recurse | Select-Object -ExpandProperty VersionInfo
$location = "C:\Program Files\SAP\SAP_DotNetConnector3_Net40_x64"
$ncoAssemblies += Get-ChildItem -Path $location -Filter sapnco.dll -Recurse | Select-Object -ExpandProperty VersionInfo
$counter = 0
Write-Host "value is $ncoAssemblies"
foreach ($assembly in $ncoAssemblies) {
$fileName = $assembly.FileName

if ($assembly.FileVersion.StartsWith("3.1.")) {
Write-Host -NoNewLine "{'step': 'CheckSapConnector', 'status': 'Error', 'message': 'SAP NetWeaver Connector version 3.1 was found. You need to uninstall $fileName. Visit this link for more information: https://go.microsoft.com/fwlink/?linkid=2240708.'},"
}

if ($fileName -like "*GAC_32*") {
Write-Host -NoNewLine "{'step': 'CheckSapConnector', 'status': 'Error', 'message': 'A 32-bit version of the SAP NetWeaver Connector was found. You need to uninstall $fileName. Visit this link for more information: https://go.microsoft.com/fwlink/?linkid=2240708.'},"
}

if (($fileName -like "*GAC_64*" -or $fileName -like "*x64*") -and $assembly.FileVersion.StartsWith("3.0.")) {
$counter++
Write-Host -NoNewLine "{'step': 'CheckSapConnector', 'status': 'Success', 'message': 'SAP NetWeaver Connector 3.0 64-bit was successfully found.'},"
}
}

if ($counter -eq 0) {
Write-Host -NoNewLine "{'step': 'CheckSapConnector', 'status': 'Error', 'message': 'SAP NetWeaver Connector 3.0 64-bit was not found. Visit this link for more information: https://go.microsoft.com/fwlink/?linkid=2240708.'},"
}

Set-Location $currentLocation

$installedSoftware = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
$name = "Microsoft Visual C++ 2010 x64 Redistributable - 10.0.40219"
$obj = $installedSoftware | Where-Object { $_.GetValue("DisplayName") -eq $name }

if ($obj) {
Write-Host -NoNewLine "{'step': 'CheckVisualCPlusPlus', 'status': 'Success', 'message': '$name is installed.'}"
}
else {
Write-Host -NoNewLine "{'step': 'CheckVisualCPlusPlus', 'status': 'Error', 'message': '$name is not installed.'}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
<#
.SYNOPSIS
Validates Kerberos Configuration.
.DESCRIPTION
This script validates Kerberos configuration.
.PARAMETER sapCclDllPath
The path to the SAP Common Crypto Library Dll.
.PARAMETER sapCclIniPath
The path to the sapcrypto.ini file
.PARAMETER sapServicePrincipalName
The SAP Service Principal Name
.PARAMETER servicePrincipal
The Service Principal
.PARAMETER opdgServicePrincipal
The OPDG Service Principal
#>

param (
[string]$sapCclDllPath,
[string]$sapCclIniPath,
[string]$sapServicePrincipalName,
[string]$servicePrincipal,
[string]$opdgServicePrincipal
)

# Required for Kerberos checks
$module = Get-Module -ListAvailable -Name ActiveDirectory

if ($module) {
Write-Host -NoNewLine "{'step': 'CheckActiveDirectoryPowerShellModule', 'status': 'Success', 'message': 'The ActiveDirectory PowerShell module is installed.'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckActiveDirectoryPowerShellModule', 'status': 'Error', 'message': 'The ActiveDirectory PowerShell module is not installed. Kerberos checks can not be performed. Install it by following this link: https://go.microsoft.com/fwlink/?linkid=2240709.'},"
}

#CheckCommonCryptoLibVersion
$path = $sapCclDllPath
$minimumVersion = "8.5.25.0"

try {
$actualVersion = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($path).FileVersion
}
catch {
Write-Host -NoNewLine "{'step': 'CheckCommonCryptoLibVersion', 'status': 'Error', 'message': 'CommonCryptoLibVersion error occurred: $_. Did you specify the correct path to the SAP CommonCryptoLib DLL?'},"
return
}

if ([version]$actualVersion -ge [version]$minimumVersion) {
Write-Host -NoNewLine "{'step': 'CheckCommonCryptoLibVersion', 'status': 'Success', 'message': 'SAP Common Crypto Library is running version $actualVersion.'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckCommonCryptoLibVersion', 'status': 'Error', 'message': 'SAP Common Crypto Library is running an old version $actualVersion. Download the latest version of the SAP Common Crypto Library from SAP.'},"
}

#CheckSapCryptoIniFile
$path = $sapCclIniPath

if (-not $path) {
Write-Host -NoNewLine "{'step': 'CheckSapCryptoIniFile', 'status': 'Warning', 'message': 'Skipping SapCryptoIniFile check because no file path was provided.'},"
return
}

$clientRole = "ccl/snc/enable_kerberos_in_client_role=1"

try {
$iniContent = Get-Content -Path $path -ErrorAction Stop
}
catch {
Write-Host -NoNewLine "{'step': 'CheckSapCryptoIniFile', 'status': 'Error', 'message': 'SapCryptoIniFile error occurred: $_. Did you specify the correct path to the sapcrypto.ini file?'},"
return
}

if ($iniContent -match [regex]::Escape($clientRole).Replace('=', '\s*=\s*')) {
Write-Host -NoNewLine "{'step': 'CheckSapCryptoIniFile', 'status': 'Success', 'message': 'sapcrypto.ini has the correct parameters: $clientRole.'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckSapCryptoIniFile', 'status': 'Error', 'message': 'sapcrypto.ini is missing the correct parameters. Modify sapcrypto.ini and add $clientRole.'},"
}

#checkSystemEnvVariable -variableName "CCL_PROFILE"

if ($env:CCL_PROFILE) {
Write-Host -NoNewLine "{'step': 'CheckSapCryptoIniFile', 'status': 'Success', 'message': 'System Environment variable CCL_PROFILE exists'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckSapCryptoIniFile', 'status': 'Error', 'message': 'Need to create a CCL_PROFILE system environment variable and set its value to the path to sapcrypto.ini.'},"
}

#CheckServicePrincipalName
$sapServicePrincipalName = $sapServicePrincipalName

if (-not $sapServicePrincipalName) {
Write-Host -NoNewLine "{'step': 'CheckServicePrincipalName', 'status': 'Warning', 'message': 'Skipping ServicePrincipalName check because no service principal name was provided.'},"
return
}
try {
$servicePrincipal = Get-ADUser -Filter { ServicePrincipalNames -like $sapServicePrincipalName } -Properties ServicePrincipalNames -ErrorAction Stop
}
catch {
Write-Host -NoNewLine "{'step': 'CheckServicePrincipalName', 'status': 'Error', 'message': 'ServicePrincipalName error occurred: $_.'},"
return
}

if ($servicePrincipal) {
Write-Host -NoNewLine "{'step': 'CheckServicePrincipalName', 'status': 'Success', 'message': 'Service Principal Name $sapServicePrincipalName exists on $servicePrincipal'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckServicePrincipalName', 'status': 'Error', 'message': 'Service Principal Name $sapServicePrincipalName does not exist in Active Directory.'},"
}

#CheckServicePrincipalSupportedEncryptionTypes
$servicePrincipal = $servicePrincipal
if (-not $servicePrincipal) {
Write-Host -NoNewLine "{'step': 'CheckServicePrincipalSupportedEncryptionTypes', 'status': 'Warning', 'message': 'Skipping ServicePrincipalSupportedEncryptionTypes check because no service principal was provided.'},"
return
}
# All the decimal values that contain AES encryption types
# https://go.microsoft.com/fwlink/?linkid=2240296
$aesEncryptionTypes = @(8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31)

try {
$supportedEncryptionTypes = Get-ADUser $servicePrincipal -Properties msDS-SupportedEncryptionTypes -ErrorAction Stop
$value = $supportedEncryptionTypes."msDS-SupportedEncryptionTypes"
}
catch {
Write-Host -NoNewLine "{'step': 'CheckServicePrincipalSupportedEncryptionTypes', 'status': 'Error', 'message': 'ServicePrincipalSupportedEncryptionTypes error occurred: $_.'},"
return
}

if ($aesEncryptionTypes.Contains($value)) {
Write-Host -NoNewLine "{'step': 'CheckServicePrincipalSupportedEncryptionTypes', 'status': 'Success', 'message': 'AES is enabled (msDS-SupportedEncryptionTypes => $value) for $servicePrincipal.'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckServicePrincipalSupportedEncryptionTypes', 'status': 'Error', 'message': 'AES is missing (msDS-SupportedEncryptionTypes) for $servicePrincipal.'},"
}

#CheckAllowedToDelegateTo
$servicePrincipal = $opdgServicePrincipal
$servicePrincipalName = $sapServicePrincipalName

# Checks if OPDG servicePrincipal is allowed to delegate to the SAP service principal name
if (-not $servicePrincipal -or -not $servicePrincipalName) {
Write-Host -NoNewLine "{'step': 'CheckAllowedToDelegateTo', 'status': 'Warning', 'message': 'Skipping AllowedToDelegate check because no service principal name was provided.'},"
return
}

try {
$allowedToDelegateTo = Get-ADUser $servicePrincipal -Properties msDS-AllowedToDelegateTo -ErrorAction Stop
$value = $allowedToDelegateTo."msDS-AllowedToDelegateTo"
}
catch {
Write-Host -NoNewLine "{'step': 'CheckAllowedToDelegateTo', 'status': 'Error', 'message': 'AllowedToDelegateTo error occurred: $_.'},"
return
}

if ($null -ne $value -and $value.Contains($servicePrincipalName)) {
Write-Host -NoNewLine "{'step': 'CheckAllowedToDelegateTo', 'status': 'Success', 'message': 'Delegation is enabled (msDS-AllowedToDelegateTo => $value) for $servicePrincipal.'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckAllowedToDelegateTo', 'status': 'Error', 'message': 'Delegation is disabled (msDS-AllowedToDelegateTo) for $servicePrincipal. Check the $servicePrincipal account in Active Directory and add $servicePrincipalName on the Delegation tab.'},"
}

#CheckTrustedToAuthForDelegation
$servicePrincipal = $opdgServicePrincipal
# Checks if OPDG service principal in Active Directory has "Use any authentication protocol" enabled on Delegation tab
if (-not $servicePrincipal) {
Write-Host -NoNewLine "{'step': 'CheckTrustedToAuthForDelegation', 'status': 'Warning', 'message': 'Skipping TrustedToAuthForDelegation check because no service principal name was provided.'},"
return
}

try {
$trustedToAuthForDelegation = Get-ADUser -Identity $servicePrincipal -Properties TrustedToAuthForDelegation -ErrorAction Stop | Select-Object TrustedToAuthForDelegation
$value = $trustedToAuthForDelegation."trustedToAuthForDelegation"
}
catch {
Write-Host -NoNewLine "{'step': 'CheckTrustedToAuthForDelegation', 'status': 'Error', 'message': 'TrustedToAuthForDelegation error occurred: $_.'},"
return
}

if ($value) {
Write-Host -NoNewLine "{'step': 'CheckTrustedToAuthForDelegation', 'status': 'Success', 'message': 'TrustedToAuthForDelegation enabled ($value) for $servicePrincipal.'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckTrustedToAuthForDelegation', 'status': 'Error', 'message': 'TrustedToAuthForDelegation disabled for $servicePrincipal. Check the $servicePrincipal account in AD and enable 'Use any authentication protocol' on Delegation the tab.'},"
}

#CheckActAsPartOfOperatingSystem
$servicePrincipal = $opdgServicePrincipal
# Checks OPDG operating system that service servicePrincipal has "Act as part of the operating system" privilege
if (-not $servicePrincipal) {
Write-Host -NoNewLine "{'step': 'CheckActAsPartOfOperatingSystem', 'status': 'Warning', 'message': 'Skipping ActAsPartOfOperatingSystem check because no service principal name was provided.'},"
return
}

try {
$accountSid = Get-ADUser -Identity $servicePrincipal -Properties ObjectGUID | Select-Object SID | Out-Null
}
catch {
Write-Host -NoNewLine "{'step': 'CheckActAsPartOfOperatingSystem', 'status': 'Error', 'message': 'ActAsPartOfOperatingSystem error occurred: $_.'},"
return
}

# This is not a PowerShell cmdlet, so we need to use the old command line tool
secedit /export /cfg $env:TEMP\secpol.cfg | Out-Null

# Checks if the secedit command was successful or not
if ($LASTEXITCODE -ne 0) {
Write-Host -NoNewLine "{'step': 'CheckActAsPartOfOperatingSystem', 'status': 'Error', 'message': 'ActAsPartOfOperatingSystem failed. Try running with an elevated PowerShell prompt.'},"
return
}

$value = (Get-Content $env:TEMP\secpol.cfg | Select-String "SeTcbPrivilege").ToString()
Remove-Item $env:TEMP\secpol.cfg
$servicePrincipal = $servicePrincipal.replace("\", "\\")
if ($value.Contains($accountSid.SID.Value)) {
Write-Host -NoNewLine "{'step': 'CheckActAsPartOfOperatingSystem', 'status': 'Success', 'message': 'ActAsPartOfOperatingSystem enabled ($value) for $servicePrincipal.'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckActAsPartOfOperatingSystem', 'status': 'Error', 'message': 'ActAsPartOfOperatingSystem disabled ($value) for $servicePrincipal. Check the 'Act as part of the operating system' property of the $servicePrincipal in the Local Security Policy console.'},"
}

#CheckImpersonateAClientAfterAuthentication
$servicePrincipal = $opdgServicePrincipal
# Checks OPDG operating system that service principal has "Impersonate a client after authentication" privilege
if (-not $servicePrincipal) {
Write-Host -NoNewLine "{'step': 'CheckImpersonateAClientAfterAuthentication', 'status': 'Warning', 'message': 'Skipping ImpersonateAClientAfterAuthentication check because no service principal name was provided.'},"
return
}

try {
$accountSid = Get-ADUser -Identity $servicePrincipal -Properties ObjectGUID -ErrorAction Stop | Select-Object SID
}
catch {
Write-Host -NoNewLine "{'step': 'CheckImpersonateAClientAfterAuthentication', 'status': 'Error', 'message': 'ImpersonateAClientAfterAuthentication error occurred: $_.'},"
return
}

# This is not a PowerShell cmdlet, so we need to use the old command line tool
secedit /export /cfg $env:TEMP\secpol.cfg | Out-Null

# Checks if the secedit command was successful or not
if ($LASTEXITCODE -ne 0) {
Write-Host -NoNewLine "{'step': 'CheckImpersonateAClientAfterAuthentication', 'status': 'Error', 'message': 'ImpersonateAClientAfterAuthentication failed. Try running with an elevated PowerShell prompt.'},"
return
}

$value = (Get-Content $env:TEMP\secpol.cfg | Select-String "SeImpersonatePrivilege").ToString()
Remove-Item $env:TEMP\secpol.cfg

if ($value.Contains($accountSid.SID.Value)) {
Write-Host -NoNewLine "{'step': 'CheckImpersonateAClientAfterAuthentication', 'status': 'Success', 'message': 'ImpersonateAClientAfterAuthentication enabled ($value).'},"
}
else {
Write-Host -NoNewLine "{'step': 'CheckImpersonateAClientAfterAuthentication', 'status': 'Error', 'message': 'ImpersonateAClientAfterAuthentication disabled ($value). Check the 'Impersonate a client after authentication' property in the Local Security Policy console.'},"
}

#CheckGatewayServiceRunsAs
$servicePrincipal = $opdgServicePrincipal
# Check what servicePrincipal the OPDG service is running as
if (-not $servicePrincipal) {
Write-Host -NoNewLine "{'step': 'CheckGatewayServiceRunsAs', 'status': 'Warning', 'message': 'Skipping GatewayServiceRunsAs check because no service principal name was provided.'}]"
return
}

$service = Get-WmiObject -Class Win32_Service -Filter "Name='PBIEgwService'"

if ($null -ne $service -and $service.StartName -ilike "*$servicePrincipal*") {
$servicePrincipal = $servicePrincipal.replace("\", "\\")
Write-Host -NoNewLine "{'step': 'CheckGatewayServiceRunsAs', 'status': 'Success', 'message': 'GatewayServiceRunsAs is running as $servicePrincipal.'}]"
}
else {
$servicePrincipal = $servicePrincipal.replace("\", "\\")
Write-Host -NoNewLine "{'step': 'CheckGatewayServiceRunsAs', 'status': 'Error', 'message': 'GatewayServiceRunsAs is not running as $servicePrincipal. Check the 'Log On As' property of the 'On-premises data gateway service' in the Windows Services console. It should be running as $servicePrincipal.'}]"
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<#
.SYNOPSIS
Tests network connection to a specified host and port.
.DESCRIPTION
This script attempts to establish a TCP connection to the specified host and port,
and reports the result in a JSON format.
.PARAMETER HostName
The hostname or IP address to connect to.
.PARAMETER Port
The port number to connect to.
#>
param (
[Parameter(Mandatory=$true)]
[string]$hostName,

[Parameter(Mandatory=$true)]
[string]$port
)

$job = Start-Job -ScriptBlock {
param($hostName, $port)
Test-NetConnection -ComputerName $hostName -Port $port
} -ArgumentList $hostName, $port

if (Wait-Job -Job $job -Timeout 10) {
$result = Receive-Job -Job $job

if ($result.TcpTestSucceeded) {
Write-Host -NoNewLine "[{'step': 'CheckNetworkConnection', 'status': 'Success', 'message': 'Successfully connected to $hostName over port $port.'}]"
}
else {
Write-Host -NoNewLine "[{'step': 'CheckNetworkConnection', 'status': 'Error', 'message': 'Failed to connect to $hostName over port $port.'}]"
}
}
else {
Write-Host -NoNewLine "[{'step': 'CheckNetworkConnection', 'status': 'Error', 'message': 'The connection to $hostName over port $port timed out after 5 seconds.'}]"
}

Remove-Job -Force -Job $job
Binary file not shown.

0 comments on commit 7719c33

Please sign in to comment.