How to protect SQL Server Database from accidental deletion? - sql-server

I would like to somehow protect databases on my SQL Server from being deleted without entering a password, even by someone with administrative access. There are times where a database has been deleted accidentally (for example, when two databases have similar names) and I'd like to prevent this from being an easy mistake to make.
I'm also open to any suggestions or alternative ideas on how to handle this. Thank you!

Create a Server Level Trigger that Rolls back any attempt to delete a database.
The Trigger will need to be disabled then re-enabled to perform any legitimate deletions.
USE [master]
GO
CREATE TRIGGER [Trig_Prevent_Drop_Database] ON ALL SERVER
FOR DROP_DATABASE
AS
RAISERROR('Dropping of databases has been disabled on this server.', 16,1);
ROLLBACK;
GO
DISABLE TRIGGER [Trig_Prevent_Drop_Database] ON ALL SERVER
GO
Or as a process:
Create a single-column, one row table in Master that will hold a database name.
Insert the name of the database in the Table.
Add an If statement to the trigger to check if the Database being dropped is identical to the Database in the table created in step 1. Otherwise Roll-back.
In this case you wouldn't need to disable the Trigger. But you're creating 2 points in the process where you define the database name.
Capturing the Database Name in a Server Level Trigger should be possible with:
SELECT CAST(eventdata().query('/EVENT_INSTANCE/DatabaseName[1]/text()') as NVarchar(128))

Related

PLSQL Insufficient Privileges While disabling a trigger from another schema

I know this sounds weird but it's an old project that I'm trying to make work.
I have two schemas SchemaA and SchemaB each one with it's own user.
I'm writing a plsql script in a package in SchemaB, but in this script I need to delete records from a table in SchemaA. But there is a trigger that won't let the delete happen.
So to make it work I have to do this command:
EXECUTE IMMEDIATE 'ALTER TRIGGER SchemaA.TDA_K$TriggerA DISABLE';
But when I do that I get ORA-01031 which is logical since SchemaB cannot disable a trigger From SchemaA
My question is, how can I GRANT the permission on the trigger (or table utilizing that trigger), to SchemaB to be able to disable it.
As per Oracle documentation
" Prerequisites
The trigger must be in your own schema or you must have ALTER ANY TRIGGER system privilege.
In addition, to alter a trigger on DATABASE, you must have the ADMINISTER database events system privilege.
"

Booting users from SQL Server

I'm not sure how to even ask this question. We are running SQL Server 2008 R2. I'm not the admin, but a programmer. I need to write an application that updates some database stuff at night. I'm going to set a flag to disable logins to the database, but I want to make a particular database unavailable to anyone except me, even if someone is already logged in to the database. My program will run nightly, as a batch file, presumably with admin privileges.
I'm expecting to produce something like a script of SQL commands. I could take the database offline, except I need to make modifications to it myself. Not sure the best way to handle this.
You can basically just set the database to "single-user" mode and use it exclusively - this T-SQL will do this:
USE master;
GO
ALTER DATABASE AdventureWorks2012
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO
(of course - replace AdventureWorks2012 with your own database name!)
This will make the database "single-user", e.g. only you have access to it, and it will boot off any users that's currently online, and will rollback all open transactions.
Read more about single user mode on MSDN!
This example sets the database to SINGLE_USER mode to obtain exclusive access. The termination option WITH ROLLBACK IMMEDIATE is specified in the first ALTER DATABASE statement. This will cause all incomplete transactions to be rolled back and any other connections to the AdventureWorks2012 database to be immediately disconnected.
Since you are using an administrative account to perform the updates, I'll assume the account is in one of these roles: db_owner, dbcreator, sysadmin. Use the ALTER DATABASE SET ... syntax to control database access during the DML operations.
The assumption is that database users you want to lock out aren't in the above mentioned roles.
USE master;
-- only allow members of db_owner, dbcreator, or sysadmin roles to access
-- database, allowing current transactions time to complete. if you want to
-- drop access immediately, add WITH ROLLBACK IMMEDIATE
ALTER DATABASE SET RESTRICTED_USER;
-- data load
-- return database to normal operating state
ALTER DATABASE SET MULTI_USER;

how to Prevent alter a database

What is the best way to prevent changes to a database or verify the integrity of this, so that it can not be altered from an application created for this database.
assuming you have a username and password to access the database permits reading - writing.
requirements:
The user has write permissions
Do not depend on a particular system like (MySQL, Oracle, SQL Server)
solution I'm looking for is not based on the user's permissions on the database
Most modern databases allow you to grant reading and writing permissions but while disallowing DDL commands like ALTER TABLE.
Do not give users that should not alter the DB structure permission to execute DDL.
If by "Alter" you mean change any data rows, rather than the database structure, you can grant the user only SELECT rights.
The user or account that your application uses must be granted permissions from the database server. Typically permissions include things like:
Select
Insert
Update
Delete
Alter
Drop
Only give the user account the permissions needed; in other words, don't grant Alter permission, and the application (or anyone using the same login) won't be able to alter tables.
Two strategies: 1) if you are running SQL Server, Oracle, DB2, etc, you can configure permissions so users are reader/writer by default (which means no alter permissions). 2) you can periodically check to see if someone has changed the data structure or even set up a DB trigger to detect changes and record who/when, etc (depends on your DB platform)

SQL Server 2008 - Delete data exclusively from stored procedure

I would like to stop power users from deleting data using SQL Server Management Studio. I need to archive data and add some info to the audit trail when data gets deleted.
Is there a way to stop them when they attempt to delete the data from SSMS?
Is there a way to know which process caused the deletion? such as from SSMS, application, stored proc?
Is there a way to allow only deletes from Stored Procedure?
Thanks
Create a new login and database user for this login. Then grant delete permission to this user, and revoke it from all others. Write procedure[s] that removes data, add WITH EXECUTE AS [previously created user that can delete data]. Grant other users with execute permissions to the procedure[s].
Well they are power users aren't they. You could set deny Delete permissions for them.
DENY DELETE TO [Your_User]
GO
From your second sentence I get the impression that deleting is not the real issue but that you need to archive data and create an audit trail when data is deleted. Why not use a delete trigger?

How can I get the username from a MS Access front end MDW in a SQL back end audit table?

I have an MS Access 2003 mdb and mdw which is connected to a SQL server backend. The tables are linked using a system DSN. I have a trigger on a SQL back end table which inserts a record into another back end audit table on insert, update, and delete. This all works well, but the trigger is using system_user to get the person making the record change, and the table is just recording the username the DSN is setup to use when that change is made in the linked Access table. If the DSN is set to use the generic sql username 'foo' and the MDW is using the user specific name 'bar', the audit table on the backend if recording all changes by all users as the user 'foo'. The users are logging in to the mdb with an mdw file, and I'd like to record the username from the mdw in the SQL backend. Is this at all possible?
From Access VBA you can use the CurrentUser() function to return the MDW user name. You need to find a way to tell SQL Server about that name. If you're building and submitting the DML statements from Access, you could add the CurrentUser value as a field expression.
I'm curious about using both Access user level security and SQL Server authentication. At first blush it sounds like a "belt and suspenders" approach ... except that SQL Server can be a very effective belt, while Access user level security is a comparatively ineffective set of suspenders. I would question what benefit ULS adds to your application.
Consider discarding ULS and switching to Windows Authentication for SQL server. That could be a simpler, cleaner, and more secure approach.
I bet ##spid in the trigger works because it is executed by the process doing the DML.
Just be aware that this may not always be reliable because sometimes Access opens additional connections without having any way of running your special code to log the user against the spid in use.
Update
Have you considered using the CONTEXT_INFO variable that is specific to each SQL Server session?
DECLARE #Info varbinary(30)
SET #Info = Convert(varbinary(30), 'My Username')
SET CONTEXT_INFO #Info
SELECT Left(Convert(varchar(30), CONTEXT_INFO()), CharIndex(0x0, CONTEXT_INFO()) - 1)
This may mean hitting a table behind the scenes anyway, but it's surely going to be faster than doing it yourself.

Resources