276 lines
12 KiB
Transact-SQL
276 lines
12 KiB
Transact-SQL
USE [HCITools]
|
|
GO
|
|
|
|
IF EXISTS (SELECT * FROM sys.objects o JOIN sys.schemas s ON o.schema_id = s.schema_id WHERE o.name = 'sp_ddl_alerts' AND OBJECTPROPERTY(object_id,N'IsProcedure') = 1 AND s.name = 'dba')
|
|
DROP PROCEDURE [dba].[sp_ddl_alerts]
|
|
GO
|
|
|
|
SET ANSI_NULLS ON
|
|
GO
|
|
|
|
SET QUOTED_IDENTIFIER ON
|
|
GO
|
|
|
|
|
|
|
|
|
|
|
|
CREATE PROCEDURE [dba].[sp_ddl_alerts]
|
|
|
|
AS
|
|
/*=============================================================================
|
|
|
|
Explication du traitement realise par la SP
|
|
-------------------------------------------
|
|
Cette SP est exécutée toute les jours et check les modifications sur les paramètres des bases.
|
|
Les résultats sont envoyés par mail
|
|
|
|
Parametres
|
|
----------
|
|
|
|
Creation : 22.08.2019 / SPE
|
|
|
|
Modifications : 06.09.19 / SPE : SQL 2014 compatibility modifications
|
|
27.09.19 / SPE : Temporary remove trustworth check
|
|
09.02.21 / SPE : #TFS62610# - Update all mail configurations to avoid SPAM
|
|
17.03.22 - FLA : Change DBA mail
|
|
17.08.23 / SPE : OCTPDBA-726: Replace mail profile name APSSQL_MAIL_PROFILE into AzureManagedInstance_dbmail_profile to be SQL managed instances compatible
|
|
|
|
=============================================================================*/
|
|
|
|
SET NOCOUNT ON;
|
|
|
|
/*------------------- Declaration des variables --------------------*/
|
|
|
|
DECLARE @errno int,
|
|
@cvCurrentOrganizationalUnit int,
|
|
@subsidiary_id int,
|
|
@totAlerts int,
|
|
@totDDL int,
|
|
@html nvarchar(max),
|
|
@errmsg varchar(255),
|
|
@email varchar(255),
|
|
@subject varchar(255),
|
|
@out_default_value varchar(60),
|
|
@format varchar(60),
|
|
@mailImportance varchar(6),
|
|
@ou varchar(3)
|
|
|
|
|
|
|
|
/*-------------------------- Traitement ---------------------------*/
|
|
BEGIN TRY
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------------------------- */
|
|
/* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 1 : RETRIEVE FORMAT AND OU CODE /////////////////////////////////////////////////// */
|
|
/* ------------------------------------------------------------------------------------------------------------------------------------- */
|
|
|
|
IF EXISTS(SELECT 1 FROM [master].[cfg].[InstanceContext] WHERE Business = 'TPPHAR')
|
|
BEGIN
|
|
/* Get the cvCurrentOrganizationalUnit */
|
|
EXEC arizona.dbo.sp_bmc_Bmc_Applic_Default
|
|
@in_job_type = 3,
|
|
@in_param_int_1 = null,
|
|
@in_param_int_2 = null,
|
|
@in_param_varchar_1 = 'cvCurrentOrganizationalUnit',
|
|
@out_default_value = @out_default_value OUTPUT,
|
|
@out_param_int_1 = null;
|
|
|
|
SELECT @cvCurrentOrganizationalUnit = convert(int,@out_default_value);
|
|
|
|
/* Check if we have a value, if not leave this SP */
|
|
IF @cvCurrentOrganizationalUnit is null
|
|
BEGIN
|
|
SELECT @errno = 70001,
|
|
@errmsg = '(APS) Error cvCurrentOrganizationalUnit does not exist!';
|
|
goto error_99;
|
|
END
|
|
|
|
/* Get the subsidiary id and OU code */
|
|
SELECT @subsidiary_id = ou.OU_subsidiary, @ou = ou.OU_Code
|
|
FROM arizona.dbo.Organizational_unit ou with (nolock)
|
|
WHERE ou.Organizational_unit_ID = @cvCurrentOrganizationalUnit;
|
|
|
|
/* Check if we have a value, if not leave this SP */
|
|
IF @subsidiary_id is null
|
|
BEGIN
|
|
SELECT @errno = 70001,
|
|
@errmsg = '(APS) Error subsidiary_id does not exist!';
|
|
goto error_99;
|
|
END
|
|
|
|
/* Get the current format */
|
|
SELECT @format = sub.SUB_code
|
|
FROM arizona.dbo.Subsidiary sub with (nolock)
|
|
WHERE sub.Subsidiary_ID = @subsidiary_id;
|
|
|
|
/* Check if we have a value, if not leave this SP */
|
|
IF @format is null
|
|
BEGIN
|
|
SELECT @errno = 70001,
|
|
@errmsg = '(APS) Error format does not exist!';
|
|
goto error_99;
|
|
END
|
|
|
|
/* Change the value into a compatible format */
|
|
IF @format = 'COOP'
|
|
BEGIN
|
|
SET @format = 'CVI'
|
|
END
|
|
|
|
IF @format = 'CENT'
|
|
BEGIN
|
|
SET @format = 'SUN'
|
|
END
|
|
|
|
IF @format = '000'
|
|
BEGIN
|
|
SET @format = 'AAI'
|
|
END
|
|
END
|
|
ELSE
|
|
BEGIN
|
|
SELECT @format = DnsAlias FROM [master].[cfg].[Identity]
|
|
SET @ou = ''
|
|
END
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------------------------- */
|
|
/* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 2 : RETRIEVE DDL EVENTS /////////////////////////////////////////////////// */
|
|
/* ------------------------------------------------------------------------------------------------------------------------------------- */
|
|
|
|
/* Temp table #AlterRules with alerts template */
|
|
CREATE TABLE #AlterRules(AlertRule varchar(100))
|
|
|
|
/* Template with all DO NOT settings */
|
|
INSERT INTO #AlterRules(AlertRule)
|
|
VALUES ('AUTO_CLOSE ON'),('AUTO_CREATE_STATISTICS OFF'),('AUTO_SHRINK ON'),('ALLOW_SNAPSHOT_ISOLATION ON'),('ANSI_NULL_DEFAULT OFF'),('ANSI_NULL OFF'),('ANSI_PADDING ON'),
|
|
('ANSI_WARNINGS ON'),('ARITHABORT OFF'),('CONCAT_NULL_YIELDS_NULL OFF'),('DB_CHAINING ON'),('DATE_CORRELATION_OPTIMIZATION ON'),('READ_COMMITTED_SNAPSHOT ON'),('NUMERIC_ROUNDABORT OFF'),
|
|
('PARAMETERIZATION FORCED'),('QUOTED_IDENTIFIER OFF'),('RECURSIVE_TRIGGERS ON'),('TRUSTWORTHY ON'),('PAGE_VERIFY NONE'),('PAGE_VERIFY TORN_PAGE_DETECTION'),('ENCRYPTION ON')
|
|
|
|
/* Insert into #DDLAlertLog temp table all DDL events of type alter database for the last 24 hours */
|
|
SELECT DA_App_Name,
|
|
DA_Host_Name,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/PostTime)[1]','NVARCHAR(MAX)') AS PostTime,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/SPID)[1]','NVARCHAR(MAX)') AS SPID,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/ServerName)[1]','NVARCHAR(MAX)') AS ServerName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/LoginName)[1]','NVARCHAR(MAX)') AS LoginName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/UserName)[1]','NVARCHAR(MAX)') AS UserName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/DatabaseName)[1]','NVARCHAR(MAX)') AS DatabaseName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/SchemaName)[1]','NVARCHAR(MAX)') AS SchemaName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/ObjectName)[1]','NVARCHAR(MAX)') AS ObjectName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/ObjectType)[1]','NVARCHAR(MAX)') AS ObjectType,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)') AS CommandText,
|
|
REPLACE(REPLACE(REPLACE(SUBSTRING(LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(DA_Event_Xml.value('(./EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)'), CHAR(10), CHAR(32)),CHAR(13), CHAR(32)),CHAR(160), CHAR(32)),CHAR(9),CHAR(32)))), CHARINDEX('SET', REPLACE(DA_Event_Xml.value('(./EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)'),' ','')) + 6, LEN(REPLACE(DA_Event_Xml.value('(./EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)'),' ',''))),'WITHNO_WAIT',''),'WITHROLLBACKIMMEDIATE',''),' ','') AS CommandAction
|
|
INTO #DDLAlertLog
|
|
FROM [master].[dba].[DDL_audit]
|
|
WHERE DA_Event_Xml.value('(./EVENT_INSTANCE/EventType)[1]','NVARCHAR(MAX)') = 'ALTER_DATABASE'
|
|
AND DA_Event_Xml.value('(./EVENT_INSTANCE/PostTime)[1]','NVARCHAR(MAX)') > GETDATE()-1
|
|
AND DA_App_Name <> '.Net SqlClient Data Provider'
|
|
AND DA_Event_Xml.value('(./EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)') not like '%TRUSTWORTHY%'
|
|
UNION ALL
|
|
SELECT DA_App_Name,
|
|
DA_Host_Name,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/PostTime)[1]','NVARCHAR(MAX)') AS PostTime,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/SPID)[1]','NVARCHAR(MAX)') AS SPID,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/ServerName)[1]','NVARCHAR(MAX)') AS ServerName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/LoginName)[1]','NVARCHAR(MAX)') AS LoginName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/UserName)[1]','NVARCHAR(MAX)') AS UserName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/DatabaseName)[1]','NVARCHAR(MAX)') AS DatabaseName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/SchemaName)[1]','NVARCHAR(MAX)') AS SchemaName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/ObjectName)[1]','NVARCHAR(MAX)') AS ObjectName,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/ObjectType)[1]','NVARCHAR(MAX)') AS ObjectType,
|
|
DA_Event_Xml.value('(./EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)') AS CommandText,
|
|
'' AS CommandAction
|
|
FROM [master].[dba].[DDL_audit]
|
|
WHERE DA_Event_Xml.value('(./EVENT_INSTANCE/EventType)[1]','NVARCHAR(MAX)') = 'ALTER_AUTHORIZATION_DATABASE'
|
|
AND replace(DA_Event_Xml.value('(./EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)'),'[','!') not like '%!sa%'
|
|
AND DA_Event_Xml.value('(./EVENT_INSTANCE/PostTime)[1]','NVARCHAR(MAX)') > GETDATE()-1
|
|
AND DA_App_Name <> '.Net SqlClient Data Provider'
|
|
ORDER BY DA_App_Name DESC
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------------------------- */
|
|
/* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 3 : CREATE AND SEND MAIL /////////////////////////////////////////////////// */
|
|
/* ------------------------------------------------------------------------------------------------------------------------------------- */
|
|
|
|
/* Count total critical alerts and set mail level */
|
|
SELECT @totDDL = COUNT(*) FROM #DDLAlertLog AL
|
|
SELECT @totAlerts = COUNT(*) FROM #DDLAlertLog AL LEFT JOIN #AlterRules AR ON AL.CommandAction = replace(AR.AlertRule,' ','') WHERE AR.AlertRule is not null OR AL.CommandText like 'alter authorization%'
|
|
IF @totAlerts > 0
|
|
BEGIN
|
|
SET @mailImportance = 'High'
|
|
END
|
|
ELSE
|
|
BEGIN
|
|
SET @mailImportance = 'Normal'
|
|
END
|
|
|
|
IF @totDDL > 0
|
|
BEGIN
|
|
|
|
SELECT @email = DML_Recipients
|
|
FROM HCITools.dbo.DBA_Mailing_list
|
|
WHERE DML_Code = 'DBA_operator'
|
|
|
|
SET @subject = @format+@ou+': ' + convert(varchar,@totDDL) + ' DDL audit found: Database settings modified! - [' + @@SERVERNAME + ']'
|
|
SET @HTML =
|
|
N'<body>Server: ' + @format+@ou+'<br />List of all DDL audit events (ALTER DATABASE) for the last day: <br /><br /><table border="1">' +
|
|
N'<tr><th>AlertLevel</th><th>Application Name</th><th>Host Name</th><th>Modified date</th><th>SPID</th><th>Server Name</th><th>Login Name</th><th>User Name</th><th>Database Name</th><th>Schema</th><th>Object</th><th>Type</th><th>Command</th></tr>' +
|
|
CAST(( SELECT CASE WHEN AR.AlertRule is null AND UPPER(AL.CommandText) not like 'ALTER AUTHORIZATION%' THEN 'INFO' ELSE 'CRITICAL' END AS 'td','',AL.DA_App_Name AS 'td','',
|
|
DA_Host_Name AS 'td','',
|
|
PostTime AS 'td','',
|
|
SPID AS 'td','',
|
|
ServerName AS 'td','',
|
|
isnull(LoginName,'') AS 'td','',
|
|
isnull(UserName,'') AS 'td','',
|
|
isnull(DatabaseName,'') AS 'td','',
|
|
isnull(SchemaName,'') AS 'td','',
|
|
isnull(ObjectName,'') AS 'td','',
|
|
isnull(ObjectType,'') AS 'td','',
|
|
CommandText AS 'td'
|
|
FROM #DDLAlertLog AL
|
|
LEFT JOIN #AlterRules AR
|
|
ON AL.CommandAction = replace(AR.AlertRule,' ','')
|
|
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX)) +
|
|
N'</table></body>' ;
|
|
|
|
/* Get default mailbox profile name */
|
|
DECLARE @defaultprofilname varchar(100)
|
|
SELECT DISTINCT @defaultprofilname = p.name FROM msdb.dbo.sysmail_profile p JOIN msdb.dbo.sysmail_principalprofile pp ON pp.profile_id = p.profile_id AND pp.is_default = 1
|
|
|
|
/* SEND MAIL */
|
|
EXEC msdb.dbo.sp_send_dbmail
|
|
@profile_name = @defaultprofilname,
|
|
@recipients = @email,
|
|
@body = @html,
|
|
@importance = @mailImportance,
|
|
@subject = @subject,
|
|
@body_format = 'HTML';
|
|
END
|
|
|
|
/* Drop temp tables */
|
|
DROP TABLE #DDLAlertLog
|
|
DROP TABLE #AlterRules
|
|
|
|
END TRY
|
|
BEGIN CATCH
|
|
SELECT @errno = 70003,
|
|
@errmsg = 'error on sp_ddl_alerts! ' + error_message()
|
|
goto error_99
|
|
END CATCH;
|
|
|
|
/*------------------ Retour au programme appelant -----------------*/
|
|
|
|
RETURN(@@error);
|
|
|
|
/*---------------------- Traitement des erreurs ----------------------*/
|
|
error_99:
|
|
RAISERROR (@errmsg, 16, 1);
|
|
RETURN(@errno);
|
|
|
|
|
|
GO
|
|
|
|
|