I am trying to configure auditing on my SQL Server using Service Broker. I did all the configuration needed to capture the DDL Events (queue, routes, endpoints, event notification). It is working properly except that I am not able to get the hostname of the client from where the DDL event originated from.
Using the service broker's activation procedure, I tried reading the value from the message_body, but there's no xml element that contains the hostname. I can see a value for the SPID but am unable to make use of it. Exec'ing sp_who and querying sys.processes against this SPID doesn't return any value. And running sp_who without parameter shows only one process (I think it's the background process used by the service broker). Is it all because the message was sent asynchronously? But why will it cause the activation context to see different data on sys.processes view?
I am aware that there are DDL triggers that can achieve the same goal, but it seems it is tightly coupled to the command that causes it to fire. So if the triggers fails, the command will also fail.
UPDATE: I managed to retrieve the Hostname by using a combination of xp_cmdshell and sqlcmd (command line app). But I also realized that since the message is asynchronous, it is not always reliable (The SPID who issue the DDL command might have been disconnected already before the message is read from the queue).
I'm not exactly sure what you're trying to implement here, but it's expected that activated procedure will only see a subset of rows in DMVs. This has to do with activation context which often impersonates a different user that you use when debugging the procedure. That impersonated user will only see these rows of server-level views and DMVs to which it has permissions. See here and here for more info.
Related
I need to be able to send an XMPP message when a row gets inserted into a particular table in our SQL Server database (and have it not make the insert fail if the XMPP server or code isn't available/fails/etc).
Is this possible without causing the insert to fail in some circumstances?
To avoid potentially blocking your database application, I'd recommend NOT to send any external messages directly from a trigger. After all, the trigger executes in the context of the SQL statement that caused it to fire, and if the trigger is delayed, then your statement will have to wait until the trigger is done (or has timed out).
Instead, what I'd do is this:
insert a row into a "command" table with enough information to be able to later send your XMPP message - this can be done in the trigger
have a separate piece of code, e.g. a scheduled SQL Server job, that checks that "Command" table every x minutes or hours or however frequently (or infrequently) that you need - and this job running separately and independently from your application should them attempt to send out those messages, and handle any potential error situations - while your main application happily works along not bothered by any delays, time outs etc.
I want to call a CLR inside a service broker queue activated store procedure but doing this causes the queue to be disabled - POISON_MESSAGE_HANDLING (STATUS = ON).
Basically, the CLR just calls a webservice to post the data it recieves.
Is there a permission or something I need to do first ?
The activated proc '[dbo].[ProcessOrders]' running on queue 'App01.dbo.InstTargetQueue' output the following: 'Could not find stored procedure 'dbo.ProcessOrders
This error indicates that the queue is configured with a stored procedure that was dropped from the database, perhaps. Can you double check that the procedure exists? Perhaps you have a typo, eg. an extra space, in the queue configuration? Run select * from sys.service_queues and double-check that the activated procedure name is exactly what you expect. Run select * from sys.procedures and make sure the procedure exists and is named as you expect.
To answer your question about CLR: first and foremost I would urge you to move the webservice calls outside of the database. Monitor the queue with an external process service, and post the web service call from your process, not from inside the database.
If you insist on calling webservices from SQLCLR, then this is what you need to know:
CLR procedures require EXTERNAL_ACCESS on the assembly to be allowed to call web services
Activated procedures run in an 'execute as' sandboxed environment, see Why does feature … not work under activation?
The sandboxed environment prevents EXTERNAL_ACCESS
So you need to exit the sandboxed environment of the activated procedure, and this can be done either by marking the database as TRUSTWORTHY, or by signing the procedure, see Signing an activated procedure. But right now your problem seem to be a simple name mismatch.
If you keep your web services inside SQLCLR (and I strongly discourage that) then please read about Thread.BeginThreadAffinity() and ServicePointManager.DefaultConnectionLimit (the second applies to an external process as well, not only SQLCLR).
I've a scenario where I've to send a mail after checking a condition after every insert in a table.
Is trigger the right way to do it?
My second question would be as to what approach to take
Should I directly send a mail from the DB. (Note: My DBserver and Mail server are in different networks, might've to create firewall rule exception)
Should I have a CLR-sproc. From the DB, I call the CLR-sproc and CLR-sproc calls a service and from there sends the mail.
Is there a better approach?
Both SQL Server DBMail and a CLR proc will use SMTP to send the email. So, why add complexity?
In addition, sending an email via DBMail or CLR will require processing on INSERT. Note that DBMail uses a queue so will impact less than running a CLR procedure.
A trigger is a good way to do it. However, consider using a stored procedure to do the ISNERT with the email sent outside of the transaction (you'll have an implicit one because of the INSERT). Sending in a trigger means it is part of the implicit transaction for the INSERT.
From a security perspective, SQLMachine still needs access to SMTPMachine, whether using DBMail or a service call by a CLR Proc.
1) Yes, a trigger would be the right way of performing an action after every insert
2) SQL server has a feature called Database Mail which looks like it will do what you want (although I've never used it myself)
PROBLEM BACKGROUND
Sorry if this is a bit tedious to read, but please bear with me.
I have been tasked to determine the most restrictive security permissions...or rather investigate if more restrictive security settings can be configured for the SQL server login our program uses, yet still function as normal.
Currently the program runs as a Windows service configured to log on using a Windows user account that has been configured in SQL server with trusted auth. The login used has been assigned a db_owner role and the service works fine like that.
So to narrow the permissions for this user I removed the db_owner rights and assigned it to the db_datareader and db_datawriter roles. Unfortunately this causes a problem and when I start up the service I get an error dialogue displaying:
Error 1053: the service did not respond to the start or control request in a timely fashion.
and in the event viewer under the System events are logged:
event 7009 (timeout waiting for..to connenct)
event 7000 (the service did not respond to the start or control )
My problem is the code base is really large and I'm not sure what exactly to look for that would require db_owner permissions (it sets permissions maybe?).
QUESTION
What should I be looking for in a program that executes SQL that would cause it to require db_owner permissions?
In case the first question is too general: is there an easy way/any tools I can use to figure out what a Windows service is trying to do during start-up 'SQL wise' if I get system error events logged:
event 7009 (Timeout (30000 milliseconds) waiting for the ... service to connect)
event 7000 (The service did not respond to the start or control request in a timely fashion).
BTW I tried running profiler with all audit events selected, but still get nothing logged when starting the service.
This is such a broad question without knowing the architecture of your service and how it communicates with SQL Server. Are you using in-line SQL? Stored Procedures?
I think you'd best tackle this issue by starting from the service's code and tracing the execution path from the start and see what is being executed on/against SQL Server.
Alternatively, if you are using stored procedures, you may want to script them all out into a file and search on some common T-SQL commands limited to a db_owner, such as CREATE, DROP, ALTER.
I need to signal a running application (Windows service) when certain things happen in SQL Server (2005). Is there a possibility to send a message from a trigger to an external application on the same system?
You can use a SQL Service Broker queue to do what you want.
The trigger can create a conversation and send a message on the queue.
When it starts, the external process should connect to the database and issue a WAITFOR (RECEIVE) statement on this queue. It will receive the message when the trigger sends it.
Not sure DBA's would approve of this, but there is a way to run commands using xp_cmdshell
"Executes a given command string as an operating-system command shell and returns any output as rows of text. Grants nonadministrative users permissions to execute xp_cmdshell."
Example from MS's site:
CREATE PROC shutdown10
AS
EXEC xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server shutting down
in 10 minutes. No more connections allowed.', no_output
EXEC xp_cmdshell 'net pause sqlserver'
WAITFOR DELAY '00:05:00'
EXEC xp_cmdshell 'net send /domain: SQL_USERS ''SQL Server shutting down
in 5 minutes.', no_output
WAITFOR DELAY '00:04:00'
EXEC xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server shutting down
in 1 minute. Log off now.', no_output
WAITFOR DELAY '00:01:00'
EXEC xp_cmdshell 'net stop sqlserver', no_output
Either:
Use RAISERROR (severity 10) to fire a SQL agent alert and job.
Load a separate table that is polled periodically by a separate mail handling process. (as HLGEM suggested)
Use a stored procedure to send the message and write to the table.
Each solution decouples the transactional trigger from a potentially long messaging call.
You can send an email from a trigger, but it isn't a recommended practice becasue if the email ssystem is down, no data changes can be made to the table.
Personally if you can live with less than realtime, I would information about the event you are interested in to another table (so the real change of data can go smoothly even if email is down for some reason.) Then I would have a job that checks that table every 5-10 minutes for any new entries and emails those out.
You can use a dbmail email message. It should not slow the trigger down if the mail server is down because the message is queued and then sent by and external (to sql) process.
The table idea sounds good if the application can access sql server.
You could also give access to that same table via sql 2005 native XML Services - which exposes procs through xml.
http://msdn.microsoft.com/en-us/library/ms345123(SQL.90).aspx
Depending on what sort of message you want to send, you could use a CLR stored procedure to connect to a socket on the running process and write the message to that. If you have no control over the process (i.e. can't modify it) you could build a bridge or use a library that can issue a message in a suitable format.
For reliable delivery, you could do something that uses MSMQ to deliver the message.
A reminder that triggers can be problematic for stuff like this because they are embedded in set-operations. And being associated with tables, they aren't very sensitive to the context in which they are fired. The problem can be if they fire on an operation that involves multiple rows, because it's hard to avoid invoking as many instances of your action as there are records in the operation. Several hundred emails are not unlikely, for instance.
Hopefully "things that happen" can be detected in closer association with the context in which they happen (which also can be interesting to try to backtrack from a trigger.)