PI Services

Le blog des collaborateurs de PI Services

Azure – Introduction à Azure Information Protection

Azure Information Protection c’est quoi ?

Azure Information Protection abrégé en AIP est une solution disponible dans Azure qui permet de classifier et de protéger des documents / e-mails.

Une fois le document / e-mail classifié il est possible de voir et de contrôler comment celui-ci est utilisé. Par exemple, il est possible d’interdire l’édition du document ou le transfert d’un mail.

Comment ça marche ?

Prérequis

AIP est présent dans les licences Office 365 à partir de la licence E3 avec comme fonctionnalités :

  • Licence E3 et + : Classification et protection des documents / e-mails par défaut et automatiques (géré par l’administrateur)
  • Licence EMS, AIP Plan 1 : Classification et protection des documents / e-mails par défaut, automatiques et manuels
  • Licence EMS, AIP Plan 2 : Prise en compte du chiffrement via HYOK (Hold your own key, chiffrement à partir d’une clé isolée du cloud afin d’augmenter la sécurité)

Le détail de l’ensemble des fonctionnalités est disponible au lien suivant https://azure.microsoft.com/en-us/pricing/details/information-protection/.

2019-01-03_145308

Mise en place

Depuis le portail Azure, rechercher Azure Information Protection.

2019-01-03_145421

 Labels

Par défaut la page d’administration d’AIP s’ouvre sur les Labels de classification. Il en existe 5 par défaut : Personnel, Public, Général, Confidentiel, Hautement Confidentiel.

2019-01-03_145450

A la création d’un label, il est possible de proteger le document. Le chiffrement s’effectue alors via une clé dans Azure ou via une clé de type HYOK.

2019-01-03_152720

Il est ensuite possible d’ajouter des permissions sur le label.

2019-01-03_145858

Policy

Une fois le label créé, il est nécessaire de créer une politique et de l’appliquée sur les utilisateurs.

2019-01-03_153007

Résultats

Il est possible d’installer sur les postes de travail le client AIP (https://www.microsoft.com/en-us/download/details.aspx?id=53018) afin d’avoir un bouton Protéger dans Outlook, Word, Excel…

En sélectionnant dans Protéger le label, un message apparaît pour informer que le mail intègre la protection.

2019-01-10_141548

Azure : La valse des CLI ... (Partie 1)

Bonjour à tous !

Le management d'une plateforme de cloud computing publique est souvent à l'image de la vie de celle-ci, c'est à dire mouvementée !
La plateforme de Microsoft, Azure, n'échappe pas a cette règle. Il est donc temps de faire un point sur les differents outils de ligne de commande mis a notre disposition pour gérer cette plateforme.

Preparation de l'environnement PowerShell

PowerShell

Powershell a été jusqu'à une période assez récente le langage privilégié pour gérer la plateforme Azure en ligne de commande, c'est pourquoi nous commencerons par lui.
La manière la plus simple de récupérer la dernière version des modules Powershell Azure est d'utiliser PowerShellGet.

La disponibilité de PowerShellGet varie suivant la version de Powershell utilisée, à toute fin utile, voici les versions de PowerShell qui sont installées par défaut avec votre OS Microsoft Windows :

  • PowerShell 2 : Windows Server 2008 R2 / Windows 7 SP1
  • PowerShell 3 : Windows Server 2012 / Windows 8
  • PowerShell 4 : Windows Server 2012 R2 / Windows 8.1
  • PowerShell 5 : Windows 10 1507 et 1511
  • PowerShell 5.1 : Windows Server 2016 et 2019 / Windows 10 1607 et supérieur

Les modules PowerShell Azure ne fonctionnant qu'à partir de la version 5 de PowerShell, si vous êtes sous Windows 7 SP1, 8.1 ou Windows Server 2008 R2 SP1, 2012, 2012 R2, il est nécéssaire de passer à la version 5.1 directement en installant le package MSI suivant : Windows Management Framework 5.1

Note : Pour ceux étant sous Windows 7 SP1 ou Windows Server 2008 R2 SP1, c'est un peu moins simple, il faut au préalable installer la version 4.5.2 du .NET Framework avant d'installer le WMF 5.1. Celle-ci est disponible ici : .NET Framework 4.5.2

Note 2 : Vous pouvez vérifier la version de PowerShell installée sur votre OS Windows avec la commande suivante :

$PSVersionTable.PSVersion

PowerShellGet

Pour ceux qui ne sont pas familier avec PowerShellGet, celui-ci permet d'installer des modules ou des scripts PowerShell à partir du repository PowerShell Gallery contenant les modules PowerShell nous intéréssant (mais beaucoup d'autres également). Les personnes connaissant l'univers des distributions Linux retrouveront ici des notions familières.

PowerShellGet, qui est lui même un module PowerShell, est présent par défaut à partir de la version 5 de PowerShell. Celà étant dit, il est préférable de le mettre à jour avant de récupérer des modules avec celui-ci. Pour se faire, deux étapes sont nécéssaires.

On installe d'abord le fournisseur de package .NET Framework NuGet (Equivalent de Apt-Get dédié au .NET Framework pour les connaisseurs). Celui-ci permet à PowerShellGet de pouvoir récupérer des modules à partir du repository PowerShell Gallery qui est de type NuGet. Il permet également à PowerShellGet de se mettre a jour puisque le module est publié lui même sur PowerShell Gallery. Voici la commande pour installer NuGet :

Install-PackageProvider Nuget –Force

Une fois que NuGet est installé, on va pouvoir mettre à jour le module PowerShellGet avec la commande suivante :

Update-Module -Name PowerShellGet

Si pour une raison X ou Y, le module n'est pas déjà installé, vous pouvez le faire avec la commande suivante :

Install-Module –Name PowerShellGet –Force

Nous pouvons donc à présent passer au coeur du sujet à savoir les modules PowerShell Azure.

Modules Azure pour PowerShell

Si vous êtes sous la version 5.X de PowerShell, il vous faut au préalable mettre à jour la version de votre .NET Framework vers la version 4.7.2 via l'installeur suivant .NET Framework 4.7.2 avant de pouvoir installer les modules PowerShell dédiés à Azure.

Module AzureRM (ARM only)

Plus récement, jusqu'en Décembre 2018, c'est le module AzureRM qui est utilisé afin de gérer la plateforme.

Officiellement, Microsoft continue de le supporter après cette date pour des corrections de bugs mais aucune nouvelle fonctionnalité Azure ne sera administrable avec. Pour cela il faudra passer par le module Az.
Les commandes sont de la même forme que celles de PowerShell, à savoir de type Verb-Noun. Exemple :

Get-AzureRmLoadBalancer

Le module est installable avec la commande suivante :

Install-Module -Name AzureRM -AllowClobber

Module Azure (alias ASM)

Pour ceux ayant débuté Azure avant l'arrivée du mode de gestion ARM (Azure Ressource Management), il y avait le mode de gestion ASM (Azure Service Management) dont le portail aujourd'hui n'est plus en activité (RIP !).

Cependant, vous avez pu remarquer que certaines ressources de type ASM persistent au sein du portail ARM sous le nom de Classic. Il est toujours possible de gérer ce type de ressources via PowerShell mais il faut installer un module supplémentaire qui vient en complément du module AzureRm. Il est installable via la commande suivante :

Install-Module -Name Azure -AllowClobber

Module Az (ASM + ARM)

C'est donc le remplaçant officiel du module AzureRm ainsi que du module Azure depuis fin 2018.
Il est installable via la commande suivante :

Install-Module -Name Az -AllowClobber

Les changements concernent principalement la partie technique du module, son utilisation est très similaire à celle de l'ancien module.
Il suffit de remplacer toutes les commandes Verb-AzureRMNoun par Verb-AzNoun. Exemple :

Get-AzLoadBalancer

Microsoft, afin de faciliter la transition, a ajouté des alias qui vous permettront d'utiliser vos anciens scripts adaptés au module AzureRm. L'activation des alias se fait via la commande suivante :

Enable-AzureRmAlias

Cependant, attention, si vous décidez d'utiliser les alias du nouveau module Az, il est impératif de désinstaller toutes les versions précédentes du module AzureRM. 

Il est possible techniquement de faire cohabiter les deux modules en les installant tous les deux sur la même machine mais Microsoft recommande la désinstallation de toutes les versions des modules AzureRm avant d'installer le module Az.

Et pour les autres OS/langages ?

Microsoft, devant le succès de sa plateforme Azure, a constaté le besoin de pouvoir administrer celle-ci depuis un poste autre que Windows ou depuis des périphériques BYOD.

C'est ainsi que son nés PowerShell 6, l'environnement Azure CLI ou encore Cloud Shell. Ces moyens d'adminitration cross-plateformes feront donc l'objet de la deuxième partie de ce billet.

SCCM - Les clients ne reçoivent plus les mises à jour après une restauration ou un changement de serveur

Suite au remplacement du serveur de site dans une infrastructure SCCM, les clients ne recevaient plus aucune mise à jour.

L’analyse du fichier de log UpdatesDeployment.log révèle le message “EnumerateUpdates for action (UpdateActionInstall) - Total actionable updates = 0 ' “.

Bien qu’il ne s’agisse pas à proprement parler d’une erreur, cette information est manifestement erronée : il y a bien des mises à jour manquantes, et l’exécution de la commande powershell suivante sur un client en donne la liste :

get-wmiobject -query "SELECT * FROM CCM_UpdateStatus" -namespace "root\ccm\SoftwareUpdates\UpdatesStore" | where {$_.status -eq "Missing"} 

Le client SCCM n’en reconnait pourtant aucune comme actionnable, comme le montre cette nouvelle commande qui ne renvoie rien :

get-wmiobject -query "SELECT * FROM CCM_SoftwareUpdate" -namespace "ROOT\ccm\ClientSDK"

Il faut savoir qu’à chaque synchronisation du catalogue WSUS, SCCM incrémente la version du catalogue. Cela permet aux agents de savoir si une version plus récente que celle qu’ils ont déjà téléchargé est disponible.

Or, lors du changement de serveur ou de la restauration d’une sauvegarde, il arrive que ce compteur reparte de 0… Si votre infrastructure SCCM existe depuis longtemps, il pourrait donc falloir des milliers de mise à jour du catalogue avant que la version n’atteigne à nouveau celle attendue par les agents!

Heureusement, le correctif est simple : il suffit de modifier dans le registre la version du catalogue afin de reprendre là où les agents s’étaient arrêté.

Commencons donc par identifier la version du catalogue qu’attendent les agents, à l’aide de la requête SQL suivante qui indique la plus haute valeur attendue :

;WITH XMLNAMESPACES ( DEFAULT 'http://schemas.microsoft.com/SystemsCenterConfigurationManager/2009/07/10/DesiredConfiguration') 
SELECT MAX(CI.SDMPackageDigest.value('(/DesiredConfigurationDigest/SoftwareUpdateBundle/ConfigurationMetadata/Provider/Operation[@Name="Detect"]/Parameter/Property[@Name="MinCatalogVersion"]/@Value)[1]', 'int')) MinCatalogVersion  
FROM [CI_ConfigurationItems] as CI  
WHERE CIType_ID = 8  

Il faut ensuite incrémenter d’une unité cette valeur, puis l’insérer dans la base de registre dans les clés suivantes :

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SMS\Components\SMS_WSUS_SYNC_MANAGER]
"ContentVersion"=x
"SyncToVersion"=x
"LastAttemptVersion"=x

Enfin, il faut exécuter une nouvelle synchronisation du catalogue dans SCCM afin que sa valeur reflète les modifications effectuées (ou attendre la prochaine synchronisation planifiée), puis exécuter un Machine policy refresh suivi d’un Update evaluation cycle sur les agents si vous souhaitez forcer le téléchargement des mises à jour.

SCOM 1801 - La console web affiche une page blanche sous IE11

Encore un petit souci de jeunesse de la nouvelle console web introduite dans SCOM 1801 lorsque vous tentez d’y accéder depuis Internet Explorer 11, une page blanche est affichée alors qu’elle fonctionne parfaitement sous Chrome/Firefox/Edge.

Pour pallier ce problème, il suffit de rajouter le HTTP Host Header suivant dans IIS, pour les sites OperationsManager et MonitoringView :

image

Nom : X-UA-Compatible

Valeur: IE=edge

image

Ce problème est normalement réglé par le passage à SCOM 1807, mais si tel n’était pas le cas, ce contournement devrait vous permettre de rétablir un accès normal!

SCOM 18xx–Voir les alertes dans la console web

Encore un souci lié à la nouvelle console web, introduite dans SCOM 1801 : lors de la création d’une Notification pour envoyer des alertes par mail, il est d’usage d’intégrer dans le corps du mail l’URL permettant d’ouvrir la console web sur l’URL en question, en utilisant le raccourci généré par le wizard :

image

image

Seulement voilà, l’URL insérée ici est incorrecte, elle ne correspond pas à la nouvelle console Web et cette adresse renvoie donc à la page d’accueil de la console !

Ce bug a été corrigé lors du passage à SCOM 1807 :

image

On voit ici que le bon format d’URL à utiliser est en réalité $Target/Property[Type="Notification!Microsoft.SystemCenter.AlertNotificationSubscriptionServer"]/WebConsoleUrl$/#/monitoring/drilldown/alert/$UrlEncodeData/Context/DataItem/AlertId$ , ce qui correspond au nouveau dashboard “Alert Drilldown”, auquel on accède normalement à partir d’un dashboard Alerts “nouvelle génération” (plus d’explications sur les nouveaux dashboards et les relations entre eux ici : https://blogs.technet.microsoft.com/momteam/2018/02/12/new-scom-web-console-blog-series-post4-the-all-new-drilldown-experience/ ) :

image


Malheureusement, cela engendre un nouveau problème : si l’utilisateur qui reçoit ce mail mais n’a qu’un accès limité à SCOM (permission accordée uniquement à quelques dossiers/vues), il risque fort de se trouver face à cet écran :

image

Ou, dans le meilleur des cas, celui-ci qui n’est pas beaucoup plus utile :

image

La raison en est que ce nouveau dashboard Alert Drilldown contient une série de widgets qui nécessitent également que l’utilisateur aie le droit d’y accéder individuellement. Or, cette permission n’est accordée par l’assistant User Roles que lorsqu’on accorde la permission à un dashboard qui y fait appel… dont aucun n’existe par défaut. Et même s’il en existait, vous pourriez très bien ne pas vouloir les montrer à tout le monde!

Un contournement serait donc de créer un dashboard Alerts “nouvelle génération”, de le cibler sur un groupe vide créé également pour l’occasion et d’en déléguer l’accès à tous les User Roles susceptibles de devoir accéder au Drilldown d’une alerte :

image


image

L’utilisateur devrait maintenant avoir accès au dashboard Drilldown alert :

image


En espérant que Microsoft corrige cela dans la prochaine version…

PowerShell/SQL–Script générant un .csv contenant le résultat d’une requête

Introduction

Le script suivant permet :

  • de récupérer le résultat d’une requête SQL dans un fichier .csv,
  • de renseigner les actions réalisées dans l’EventViewer,
  • de retourner un code d’erreur (0 ou 1) suite à l’exécution du script.

Prérequis

  • Powershell
  • SQL

Présentation du script

Variables :

[string] $server = "localhost" : Serveur SQL
[string] $database = "base" : Base SQL
[string] $query = "SELCT * FROM Table" : Requête ou procédure stockée
[string] $extractFilePath = "C:\test.csv" : Emplacemnt de génération du fichier .csv
[string] $delimiter = ";" : Délimiteur à utiliser pour la génération du fichier .csv
[int] $skipline = 1 : Nombre de ligne à tronquer (utile si l’on souhaite retirer la ligne d’entête.

Script

 

# Variables d'entrée
param
    (
    [string] $server = "localhost", 
    [string] $database = "base",
    [string] $query = "SELECT * FROM Table",
    [string] $extractFilePath = "C:\test.csv",
    [string] $delimiter = ";",
    [int] $skipline = 1

    )

#MAIN
function main
{

#Variables calculées
$full_date = Get-Date;
$custom_date = $full_date.ToString("yyyyMMdd");
$DataSet = New-Object System.Data.DataSet;
$eventsource ="CsvFromSQL_Powershell";
$eventlogname = "Application";
[int] $errorcode = 1;


#Génération de la source d'evenements si inexistante
if ([System.Diagnostics.EventLog]::SourceExists($eventsource) -eq $false) 
    {
        #write-host "Creating event source $eventsource on event log $eventlogname"
        [System.Diagnostics.EventLog]::CreateEventSource($eventsource, $eventlogname)
        #write-host -foregroundcolor green "Event source $eventsource created"
    }
        else
    {
        #write-host -foregroundcolor yellow "Warning: Event source $eventsource already exists. Cannot create this source on Event log $eventlogname"
    }

<#
$logFileExists = Get-EventLog -list | Where-Object {$_.logdisplayname -eq $eventlogname} 
if (! $logFileExists) 
    {
        New-EventLog -LogName $eventlogname -Source $eventsource
    }
#>

#Execution des fonctions et récupération du code d'erreur
$errorcode = Test-SQLConn -_server $server -_database $database;
$errorcode = sql_to_dataset -_server $server -_database $database -_query $query -_dataset $DataSet;
$errorcode = dataset_to_csv -_dataset $DataSet -_extractFilePath $extractFilePath;
return $errorcode;
}

#Test connection SQL
Function Test-SQLConn ($_server, $_database)
{
    $errorcode=0;
    $connectionString = "Data Source=$_server;Integrated Security=true;Initial Catalog=$_database;Connect Timeout=3;";
    $sqlConn = new-object ("Data.SqlClient.SqlConnection") $connectionString;
    trap
        {
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 1 -EntryType Error -Message "Cannot connect to server $_server or database $_database.";
        $errorcode=1;
        Write-Host $errorcode;
        exit
        }
    $sqlConn.Open()
    if ($sqlConn.State -eq 'Open')
        {
        $sqlConn.Close();
        Start-Sleep -s 1;
        Write-EventLog  -LogName $eventlogname -Source $eventsource -EventID 0 -EntryType Information -Message "Connected to server $_server on database $_database.";
        }
}

#Rempli un dataset à partir d'une requête SQL
function sql_to_dataset
    {
    param($_server, $_database, $_query, $_dataset);
    $connectionTemplate = "Data Source={0};Integrated Security=SSPI;Initial Catalog={1};";
    $connectionString = [string]::Format($connectionTemplate, $_server, $_database);
    $errorcode=0;
    try
        {
        $connection = New-Object System.Data.SqlClient.SqlConnection -ErrorAction stop;
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 0 -EntryType Information -Message "The SQL connection has been created successfully.";
        }
    catch
        {
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 1 -EntryType Error -Message "An error occurred when creating the SQL connection. Error Message : $_.Exception.Message";
        $errorcode=1;
        Write-Host $errorcode;
        exit;
        }

    $connection.ConnectionString = $connectionString;

    try
        {
        $command = New-Object System.Data.SqlClient.SqlCommand -ErrorAction stop;
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 0 -EntryType Information -Message "The SQL command has been created successfully.";
        }
    catch
        {
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 1 -EntryType Error -Message "An error occurred when creating the SQL command. Error Message : $_.Exception.Message";
        $errorcode=1;
        Write-Host $errorcode;
        exit;
        }
    
    $command.CommandText = $_query;
    $command.Connection = $connection;

    try
        {
        $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter -ErrorAction stop;
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 0 -EntryType Information -Message "The SQL DataMapper has been created successfully.";
        }
    catch
        {
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 1 -EntryType Error -Message "An error occurred when creating the SQL DataMapper. Error Message : $_.Exception.Message"; 
        $errorcode=1;
        Write-Host $errorcode;
        exit;
        }
    
    $SqlAdapter.SelectCommand = $command;

    try
        {
        $SqlAdapter.Fill($_dataSet) | Out-Null -ErrorAction stop;
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 0 -EntryType Information -Message "The Dataset has been filled successfully.";
        }
    catch
        {
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 1 -EntryType Error -Message "An error occurred when filling the Dataset. Error Message : $_.Exception.Message";
        $errorcode=1;
        Write-Host $errorcode;
        exit;
        }

    $connection.Close();
    return $errorcode;
    }

#Rempli un csv avec un dataset
function dataset_to_csv
{
param($_dataset, $_extractFilePath);
$errorcode=0;
    try
        {
        $_dataSet.Tables[0] | ConvertTo-Csv -NoTypeInformation -Delimiter $delimiter | select -Skip $skipline  | Set-Content $_extractFilePath -ErrorAction stop;
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 0 -EntryType Information -Message "The CSV file has been created successfully.";
        }
    catch
        {
        Start-Sleep -s 1;
        Write-EventLog -LogName $eventlogname -Source $eventsource -EventID 1 -EntryType Error -Message "An error occurred when generating the CSV file. Error Message : $_.Exception.Message";
        $errorcode=1;
        Write-Host $errorcode;
        exit;
        }
        return $errorcode;
}

main



 

SCCM–Modifier depuis SQL le Maximum package processing threads.

Introdution

ATTENTION, l’action proposée par cet article ne fait pas l’objet d’une KB.

La valeur “Maximum package processing threads” permet de limiter le nombre de distribution concurrente de packages.

Cette valeur est bornée de 1 à 50, elle peut être modifiée depuis le console d’administration dans “Configure Site Components”

image

Problématique

Suite à une mauvaise manipulation, cette valeur a été modifiée à 0. La valeur 0 étant en dehors de [0..50], l’erreur suivante apparait :

clip_image001

Résolution

Le script suivant permet de récupérer la valeur actuelle :

Select * from SC_Component_Property cp join SC_Component c on c . ID = cp . ComponentID join SC_SiteDefinition sd on sd . SiteNumber = c . SiteNumber where cp . name = 'Thread Limit' and ComponentName = 'SMS_DISTRIBUTION_MANAGER' and sd . SiteCode = 'SITECODE'
 

Le script suivant permet de modifier la valeur à 3 :

Update CP Set Value3 = 3 from SC_Component_Property cp join SC_Component c on c . ID = cp . ComponentID join SC_SiteDefinition sd on sd . SiteNumber = c . SiteNumber where cp . name = 'Thread Limit' and ComponentName = 'SMS_DISTRIBUTION_MANAGER' and sd . SiteCode = 'SITECODE'
 

SCCM/WMI – Modifier depuis WMI le Maximum package processing threads.

Introdution

ATTENTION, l’action proposée par cet article ne fait pas l’objet d’une KB.

La valeur “Maximum package processing threads” permet de limiter le nombre de distribution concurrente de packages.

Cette valeur est bornée de 1 à 50, elle peut être modifiée depuis le console d’administration dans “Configure Site Components”

image_thumb5_thumb

Problématique

Suite à une mauvaise manipulation, cette valeur a été modifiée à 0. La valeur 0 étant en dehors de [0..50], l’erreur suivante apparait :

clip_image001_thumb1_thumb

Résolution

La valeur peut être modifié depuis SQL (cf. article précèdent), mais également depuis WMI :

Lancer l’outil WMI Tester :

image_thumb1[1]

Se connecter à “root\SMS\site_NOMDUSITE” puis cliquer sur “Enum Classes…” :

image_thumb4

Rechercher la classe “SMS_SCI_Component” puis double cliquer dessus :

image_thumb8

Cliquer sur “props” puis cliquer sur “Instances” :

image_thumb10

Choisir “SMS_Distribution_Manager” :

image_thumb12

Double cliquer sur “Props” :

image_thumb1

Cliquer sur “view embedded” :

image_thumb16

Vérifier les entrées suivantes jusqu’à trouver une valeur appelée “Thread Limit”

image_thumb18

image_thumb20

Modifier la valeur “Value” à la valeur souhaitée, dans cet exemple on passe de 0 (0x0) à 3 (0x0)  :

image_thumb22

image_thumb24

Fermer toutes les fenêtre en sauvegardant chacune.

SCOM - Script de Fermeture des alertes liées a des monitors en état Healthy

Ci-dessous une nouvelle version d'un script de fermeture des alertes liées a des monitors en état Healthy. En effet meme si le cas contraire est plus fréquent (alerte fermée alors que le monitor est encore en état Warning ou Critical), il se peut que l'on doivent fermer les alertes de monitors en état Healthy.

Le script affiche clairement la sortie des alertes a traiter et log cette sortie dans l'eventlog.

 

# SCRIPT TO CHECK INCONSISTENCY BETWEEN NOT CLOSED ALERTS AND HEALTHY MONITORS 


Param(
# Treat alerts that has been modified since less than $LastModifHours
$LastModifHours = 2
)

$ScriptName = "CloseAlertsFromHealthyMonitors.ps1"


# FUNCTIONS

# Check if a source with script name exist in operationsmanager eventlog to log some specific 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 of script $ScriptName (Value of LastModifHours is $LastModifHours hours)" -EntryType Information

# Import of Scom Module
Import-Module OperationsManager


# Get list of closed alerts with following criterias:
# - Not Closed
# - Generated by a monitor

$NotClosedAlerts = Get-SCOMAlert -ResolutionState (0..254)  | where { ($_.ismonitoralert -eq $true) -and $_.LastModified -gt (Get-Date).addhours(-$LastModifHours)}


# Variable to store the result of alert treatment.
# Header
$Result = "`n*********** CHECK INCONSISTENCY BETWEEN NOT CLOSED ALERTS AND HEALTHY MONITORS ***********"

$Result += "`n START `n"


for ($i=0;$i -le $NotClosedAlerts.GetUpperBound(0);$i=$i+1) 
{
# Display alert Nb
$NotClosedAlert = $NotClosedAlerts[$i]
$Result +=  "`n`nalert $i ------------------------------"



# Get IDs from Closed alert 
$mrid = $NotClosedAlert.monitoringruleid 
$mcid = $NotClosedAlert.monitoringclassid 
$moid = $NotClosedAlert.monitoringobjectid 



# Get corresponding class 
$monitoringclass = Get-SCOMClass -id $mcid

# Get the corresponding instance with following criterias:
# - HealthState equal Success 
$MyInstance = Get-SCOMMonitoringObject -Class $monitoringclass | where {$_.id -eq $moid -and $_.HealthState -eq "Success"} 

# If there is no instances no need to reset (exit the loop and treat the next closed alert)
If(!($MyInstance))
{
$Result += "No Instance found in Success state for the alert `"$($NotClosedAlert.Name)`" - NO NEED TO CLOSE ALERT"
}
Else
{
$Result += "`nThe following alert must be closed: `n"
$Result += "NAME: $($NotClosedAlert.Name)`n"
$Result += "ID: $($NotClosedAlert.Id)`n"
$Result += "COMPUTER OR OBJECT: $($NotClosedAlert.MonitoringObjectDisplayName)`n"
$Result += "COMPUTER OR OBJECT FULL PATH: $($NotClosedAlert.MonitoringObjectFullName)`n"
$Result += "COMPUTER OR OBJECT HEALTH STATE: $($NotClosedAlert.MonitoringObjectHealthState)`n"
$Result += "TIME RAISED: $($NotClosedAlert.TimeRaised)`n"
$Result += "TIME LAST MODIFIED: $($NotClosedAlert.LastModified)`n"



    try
    {
    Set-SCOMAlert -Alert $NotClosedAlert -ResolutionState 255
    $Result += "Closing of alert `"$($NotClosedAlert.Name)`"..."
    $Result += "-------------------------------------------------------`n`n`n"
    # Update of Alert History Text
    $NotClosedAlert.Update("Alert closed by $ScriptName script")
    }
    catch
    {
    $Result += "Error during the close of alert `"$($NotClosedAlert.Name)`" (ALERT ID: $($NotClosedAlert.Id))"
    }
}

}

$Result += "`n`n END `n"

# Check if $Result contains error of alert closing
if ($($Result | Out-String).Contains("Error during the close of alert"))
{
$Result += "At least one Error has been encountered during closing of some alerts"
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1001 -Message $Result -EntryType Warning
}
Else
{
$Result += "`n OK - Treatment of Alerts has ending without Error"
NewEventSource 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1002 -Message $Result -EntryType Information

}

# Display Result
$Result

 

 

Zabbix API with Powershell – Example

L'API de Zabbix, basée sur le standard JSON-RPC 2.0 peux bien sur etre intérrogée aussi avec Powershell.

 Ci-dessous un script montrant le principe d'interrogation de l'API, en recuperant certaines infos.

 Vous devez renseigner un compte (<my_zabbix_account>) avec au minimum les droits de lecture sur Zabbix, et le nom ou l'ip du serveur Front Web (<zabbix_frontweb_server>).

 

### Query Zabbix Through native zabbix json api

    $credential = Get-Credential -Credential "my_zabbix_account"

$baseurl = 'https://<name_or_ip_of_front_server>/zabbix'
$params = @{
    body =  @{
        "jsonrpc"= "2.0"
        "method"= "user.login"
        "params"= @{
            "user"= $credential.UserName
            "password"= $credential.GetNetworkCredential().Password
        }
        "id"= 1
        "auth"= $null
    } | ConvertTo-Json
    uri = "$baseurl/api_jsonrpc.php"
    headers = @{"Content-Type" = "application/json"}
    method = "Post"
}

[System.Net.ServicePointManager]::SecurityProtocol = 'tls12'
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

$result = Invoke-WebRequest @params -UseBasicParsing



$params.body = @{
    "jsonrpc"= "2.0"
    "method"= "host.get"
    "params"= @{
        output = "extend"
		selectFunctions = "extend"
		selectLastEvent = "extend"
		selectGroups = "extend"
		selectHosts = "extend"
    }
    auth = ($result.Content | ConvertFrom-Json).result
    id = 2
} | ConvertTo-Json

$result = Invoke-WebRequest @params -UseBasicParsing
$result = $result.Content | ConvertFrom-Json