Le blog technique

Toutes les astuces #tech des collaborateurs de PI Services.

#openblogPI

Retrouvez les articles à la une

Exchange 2013 – Erreur HttpEvent 15021

Problématique

Sur un serveur Exchange 2013, la connexion PowerShell ne s’effectue pas et le portail d’administration affiche une page blanche.

2018-03-29_105153

2018-03-29_105411

Dans le journal d’événements système un grand nombre d’erreur HttpEvent 15021 est présent.

2018-03-29_105128

Ces erreurs peuvent intervenir après le changement d’un certificat sur le serveur Exchange.

Résolution

Le problème vient de la liaison du certificat qui est incorrect sur le port 444. Il faut donc la supprimer et la recréer.

Pour cela, afficher l’ensemble des liaisons SSL avec la commande :

netsh http show sslcert

2018-03-29_105203

Récupérer les valeurs du hash et l’application ID de la liaison sur le port 443.

Supprimer la liaison du port 444 avec la commande :

netsh http delete sslcert ipport=0.0.0.0:444

2018-03-29_105239

Et recréer une liaison en utilisant le hash et l’application ID du port 443 avec la commande :

netsh http add sslcert ipport=0.0.0.0:444 certhash=XXXXXXX appid=”{XXXXXXXX}”

2018-03-29_105352

Dans le journal d’événements deux avertissements HttpEvent 15300 et 15301 apparaissent.

2018-03-29_105518

Une fois la modification effectuée, la connexion PowerShell et le portail d’administration sont de nouveau accessibles.

Supervision – SQL – 3 scripts pour la supervision de Always On

 

Dans le cadre d’un portage de règle de supervision, les trois scripts ci-dessous ont été crées pour remonter l’état de:

– Un Availability Group

– Un Availability Replica

– Un Database Replica

 

En pratique ils utilisent a peu près la même requête SQL. Ils contiennent des éléments propre a l’api scom mais peuvent bien sur être adapté pour être utilisé indépendamment.

Ci-dessous les 3 scripts et l’exemple du code du premier, Check_SQL_AO_AvailabilityGroupStatus_Query_Version.ps1.

 

 

#######################################################################################
#         
#
         
#          Script: SQLAlwaysOnAvailGroupStatus.ps1

#          Purpose: Shows AlwaysOn Availability Group Status
#         
#          Parameters:

#           $DBServer: ShortName of DB Server
#          $InstanceFullName: Name of SQL Instance
#          $AvailGroupName: Availability Group Name
#         
#

########################################################################################

param ( 
           
$Arguments,

           
[string]$DBServer,
           
[string]$InstanceFullName,
       
[string]$AvailGroupName
           
                          
           
)

# Create local variables from override value
.([Scriptblock]::Create($Arguments))

$Scriptname = « SQLAlwaysOnAvailabilityReplicaStatus.ps1 »

# Name of Instance
$ServerInstance = $InstanceFullName.Split(‘\’)[1]

    #Determine TcpPort Used for Instance
    try
    {
    $TcpPort = Get-ItemProperty « HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.$ServerInstance\MSSQLServer\SuperSocketNetLib\Tcp\IpAll » | select TcpPort -exp tcpport
    }
    catch
    {
    $Message = « Error during Retrieve of TCP Port Used – Check the execution of the script »
    write-host -f Yellow $Message
    $PropertyBag.AddValue(« State », »WARNING »)
    $PropertyBag.AddValue(« Message »,$Message)
    $PropertyBag.AddValue(« ReplicaName »,$AvailabilityReplicaName)
    $PropertyBag
    Exit 1
    }

# Scom Object and Property Bag
$api = New-Object -comObject “MOM.ScriptAPI” 
$PropertyBag = $api.CreatePropertyBag()

# Function  GetAODBRepStatus
Function GetAOAvailGroupStatus
                        {
                        param(
                                    [string]$TargetComputer=$DBServer,
                                    $global:Source = « $DBServer\$ServerInstance »,
                                    [string]$sqlCommand =
                                            $(« 
                                            SELECT
                                           
                                            AO_AG.name as AvailGroupName
                                            ,HADR_AO_AGS.synchronization_health as AvailGroup_SyncHealth
                                            ,HADR_AO_AGS.synchronization_health_desc as AvailGroup_SyncHealth_Desc
                                            –,SYSDB.name as DBName
                                           
                                            –,AO_AVREP.replica_server_name
                                            –,HADR_AVAIL_REP_STATE.synchronization_health as AvailReplica_SyncHealth
                                           
                                            –,HADR_AVAIL_REP_STATE.synchronization_health_desc as AvailReplica_SyncHealth_Desc

                                            –,HADR_DB_REP_STATE.synchronization_state as DBReplica_SyncState
                                            –,HADR_DB_REP_STATE.synchronization_state_desc as DBReplica_SyncState_Desc
                                            –,HADR_DB_REP_STATE.synchronization_health_desc as DBReplica_SyncHealth_Desc

                                           
                                            FROM
                                            [sys].[availability_databases_cluster] AO_DB_CLUS
                                            –INNER JOIN sys.databases SYSDB on CAST(SYSDB.group_database_id AS VARCHAR(50)) =  CAST(AO_DB_CLUS.group_database_id AS VARCHAR(50))
                                            INNER JOIN sys.dm_hadr_database_replica_states HADR_DB_REP_STATE on CAST(HADR_DB_REP_STATE.group_database_id AS VARCHAR(50)) = CAST(AO_DB_CLUS.group_database_id AS VARCHAR(50))
                                            –INNER JOIN sys.dm_hadr_availability_replica_states HADR_AVAIL_REP_STATE on HADR_AVAIL_REP_STATE.group_id = HADR_DB_REP_STATE.group_id
                                            INNER JOIN sys.availability_groups AO_AG on AO_AG.group_id = HADR_DB_REP_STATE.group_id
                                            INNER JOIN sys.dm_hadr_availability_group_states HADR_AO_AGS on HADR_AO_AGS.group_id = AO_AG.group_id
                                            –INNER JOIN [sys].[availability_replicas] AO_AVREP on AO_AVREP.replica_id = HADR_DB_REP_STATE.replica_id
                                            WHERE AO_AG.name = ‘
$AvailGroupName

                                           
                                            GROUP BY
                                            AO_AG.name
                                            ,HADR_AO_AGS.synchronization_health
                                            ,HADR_AO_AGS.synchronization_health_desc
                                            « 
                                            )
                               )

                               Try
                               {

                                                                                           
                                               

                                            $global:connectionString = « Data Source=$Source,$TcpPort; » +
                                            « Integrated Security=SSPI;  » +
                                            « Initial Catalog=master »

                                           
                                            $connection = new-object system.data.SqlClient.SQLConnection($connectionString)
                                           
                               
                                                               
                                            $connection.Open()
                                                                                 
                                                                              

                                            $command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)

                                }
                                catch
                                {
                                write-host -F Red $(« Error during sql connection – check the credentials used »).ToUpper()
                                #exit 1
                                }

                                $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
                                $set = New-Object System.Data.DataSet
                                $adapter.Fill($Set) | Out-Null

                                $connection.Close()
                                $Set.Tables

                               

                              }

# Execute function and get data
try
{
[array]$AvailGroup = GetAOAvailGroupStatus
}
catch
{
$Message = « WARNING – Error during Connection to master database or execution of sql query »
write-host -F Yellow $Message
$PropertyBag.AddValue(« State », »WARNING »)
$PropertyBag.AddValue(« Message »,$Message)
$PropertyBag.AddValue(« DBServer »,$DBServer)
$PropertyBag.AddValue(« connectstring »,$connectionString)
$PropertyBag.AddValue(« AvailGroupName »,$AvailGroupName)
$PropertyBag.AddValue(« AvailGroupStatus », »no_data »)
$PropertyBag
exit 1
}

if (!($AvailGroup))
{
$Message = « WARNING – Error – No Availability Group have been found »
write-host -F Yellow $Message
$PropertyBag.AddValue(« State », »WARNING »)
$PropertyBag.AddValue(« Message »,$Message)
$PropertyBag.AddValue(« DBServer »,$DBServer)
$PropertyBag.AddValue(« AvailGroupName », »no_data »)
$PropertyBag.AddValue(« AvailGroupStatus », »no_data »)
$PropertyBag
exit 1
}

 

try
{
$AvailGroupState = $AvailGroup  | select AvailGroup_SyncHealth_Desc -ExpandProperty AvailGroup_SyncHealth_Desc
}
catch
{
$Message = « Error during Retrieve of Availability Group State »
Write-Host -ForegroundColor Yellow $Message
$PropertyBag.AddValue(« State », »WARNING »)
$PropertyBag.AddValue(« Message »,$Message)
$PropertyBag.AddValue(« DBServer »,$DBServer)
$PropertyBag.AddValue(« AvailGroupName »,$AvailGroupName)
$PropertyBag.AddValue(« AvailGroupStatus », »no_data »)
$PropertyBag
exit 1
}

« AVAILABILITY GROUP: $AvailGroupName »

If ($AvailGroupState -eq « Healthy »)

        {
        $Message = « OK – Status of $AvailGroupName Availability Group is Healthy »
        write-host -f Green $Message
        $PropertyBag.AddValue(« State », »OK »)
        $PropertyBag.AddValue(« Message »,$Message)
        $PropertyBag.AddValue(« DBServer »,$DBServer)
        $PropertyBag.AddValue(« AvailGroupName »,$AvailGroupName)
        $PropertyBag.AddValue(« AvailGroupStatus », »Healthy »)
        $PropertyBag
        Exit 0
        }
       

ElseIf ($AvailGroupState -eq « Error »)

   
        {
        $Message = « CRITICAL – Status of $AvailGroupName Availability Group is Error »
        write-host -f Red $Message
        $PropertyBag.AddValue(« State », »CRITICAL »)
        $PropertyBag.AddValue(« Message »,$Message)
      $PropertyBag.AddValue(« DBServer »,$DBServer)
        $PropertyBag.AddValue(« AvailGroupName »,$AvailGroupName)
        $PropertyBag.AddValue(« AvailGroupStatus », »Error »)
        $PropertyBag
        Exit 0
        }
       
Else   {
        $Message = « WARNING – Status of $AvailGroupName Availability Group cannot be determined »
        write-host -f yellow $Message
        $PropertyBag.AddValue(« State », »WARNING »)
        $PropertyBag.AddValue(« Message »,$Message)
      $PropertyBag.AddValue(« DBServer »,$DBServer)
        $PropertyBag.AddValue(« AvailGroupName »,$AvailGroupName)
        $PropertyBag.AddValue(« AvailGroupStatus », »no_data »)
        $PropertyBag
        Exit 1
        }
 
 

########################################################################################

Supervision – Script de corrélation a la seconde

 

Une demande m’a été faite récemment pour la détection de l’occurrence de deux events distinct a la même seconde, ce cas particulier traduisant un problème de sécurité spécifique.

Indépendamment de l’objectif final, il s’agit d’un cas intéressant auquel le script ci-dessous a répondu. Il contient des éléments propre a l’api scom mais peux bien sur être adapté pour être utilisé indépendamment.

 

 

  ##############################################################
### SCRIPT TO DETECT SPECIFIC TWO EVENTS OCCURING AT SAME TIME #####
##############################################################

# PARAMETERS:
### $EventLog: Event Log to look in
### $EventSource: Event Source to search for 

### $FirstEventId: First event to correlate
### $SecondEventId: second event to correlate

### $LastMinutes: Last Time Window to search in
### $DayOfWeekToExclude: Day Of Week To Exclude (Example: « (‘Saturday’,’Sunday’) » )

param(
$Arguments,
$EventLog,
$EventSource,
$FirstEventId,
$SecondEventId,
$LastMinutes,
$DayOfWeekToExclude
)

$ScriptName = « CorrelateTwoSpecEvent.ps1 »

#FUNCTIONS

#Check for the existence of an event source with script name in operation manager eventlog to log some events 
        
Function NewEventSource
 
        
{
 
        
if(!(Test-Path « HKLM:\SYSTEM\CurrentControlSet\services\eventlog\Operations Manager\$ScriptName »))
 
        
{
 
        
New-EventLog -LogName « Operations Manager » -Source $ScriptName
 
        
}

        
} 

#END FUNCTIONS

#Log of script execution 
NewEventSource
 
write-eventlog -logname « Operations Manager » -Source $ScriptName -EventID 1000 -Message « Execution du script $ScriptName » -EntryType Information
 

# Create local variables from override value
.([Scriptblock]::Create($Arguments))

# Determine the moment in the week
if ((Get-date).DayOfWeek -in $DayOfWeekToExclude)
{
# If the day is in $DayOfWeekToExclude -> NO ACTION  END OF SCRIPT
Write-Host « $((Get-date).DayOfWeek) : NO ACTION – END OF SCRIPT »
Exit 0

}

# Create the Scom property bag
$ScomAPI = New-Object -comObject « MOM.ScriptAPI »
$PropertyBag = $ScomAPI.CreatePropertyBag()

$Message =     « SEARCH CRITERIAS: Log: $EventLog – Source: $EventSource – EventId: $FirstEventId or $SecondEventId `n »
$Message

try
{
New-Variable -Name « $($FirstEventId)_Events » -Force -Value $(Get-WinEvent -ErrorAction SilentlyContinue -FilterHashtable @{logname=$EventLog;ProviderName=$EventSource;id=$FirstEventId;StartTime=$(get-date).AddMinutes(-$LastMinutes)})
New-Variable -Name « $($SecondEventId)_Events » -Force -Value $(Get-WinEvent -ErrorAction SilentlyContinue -FilterHashtable @{logname=$EventLog;ProviderName=$EventSource;id=$SecondEventId;StartTime=$(get-date).AddMinutes(-$LastMinutes)})
}
catch
{
$Message = « Error during retrieve of events in the $ScriptName script »
$Message

NewEventSource
Write-EventLog -LogName « operations manager » -Source $ScriptName -EventId 1001 -EntryType Warning -Message « $Message »
Exit 1

}

#If no one of the two events id have occurence no need to continue
if (!$(Get-Variable « $($FirstEventId)_Events »).Value -and !$(Get-Variable « $($SecondEventId)_Events »).Value)
   
{
   
$Message =  « No one of the two events id have occurences in last $LastMinutes minutes – END OF SCRIPT »
   
$Message

   
Write-EventLog -LogName « operations manager » -Source $ScriptName -EventId 1002 -EntryType Information -Message « $Message »

    Exit 0
   
}

#If Only one of the two events id have occurences no need to continue
if (!$(Get-Variable « $($FirstEventId)_Events »).Value -or !$(Get-Variable « $($SecondEventId)_Events »).Value)
   
{
   
$Message = « Only one of the two events id have occurences – END OF SCRIPT »
   
$Message

   
Write-EventLog -LogName « operations manager » -Source $ScriptName -EventId 1003 -EntryType Information -Message $Message

    Exit 0
   
}

$Message = « $($(Get-Variable « $($FirstEventId)_Events« ).Value.count) occurence of event $FirstEventId and $($(Get-Variable « $($SecondEventId)_Events« ).Value.count) occurence of event $SecondEventId in the last $LastMinutes minutes »
$Message +=
« `nSTART OF COMPARAISON…`n »
#$Message

#Compare DateTimes at second level
try
{
$CompareResult = Compare-Object -ReferenceObject $(Get-Variable -Name « $($FirstEventId)_Events »).Value.timecreated.second -DifferenceObject $(Get-Variable -Name « $($SecondEventId)_Events »).Value.timecreated.second -ExcludeDifferent -IncludeEqual -Verbose
}
catch
{
$Message += « Error during comparaison of Date Creation »
$Message

NewEventSource
Write-EventLog -LogName « operations manager » -Source $ScriptName -EventId 1004 -EntryType Warning -Message $Message
Exit 1
}

#If $CompareResult is null, Events have not occureat the same time
If (!($CompareResult))
   
{
   
$Message += « Events $FirstEventId and $SecondEventId have not occured at the same second – No correlation »
   
$Message

   
NewEventSource   
   
Write-EventLog -LogName « operations manager » -Source $ScriptName -EventId 1004 -EntryType Information -Message $Message
   
   
exit 0

   
}

Else
   
{
   
NewEventSource
   
#
   
$Message += « EVENT $FirstEventId and $SecondEventId have occured at same second $($CompareResult.count) times `n »
   
$Message +=
« `nEVENTS OF LAST $LastMinutes MINUTES:`n »
       
   
$Message += $(Get-Variable « $($FirstEventId)_Events »).value | foreach {$_} | Out-String
 
   
$Message += $(Get-Variable « $($SecondEventId)_Events »).value | foreach {$_} | Out-String

   
$Message
   
Write-EventLog -LogName « operations manager » -Source $ScriptName -EventId 1005 -EntryType Information -Message $Message
   
$PropertyBag.AddValue(« State »,« CRITICAL »)
   
$PropertyBag.AddValue(« Message »,$Message)
   
   
$PropertyBag
   
}