Service Broker is working only first time - sql-server

Service Broker is working only for the first time.
I am new to service broker and learning the same. Doing it for the first time.
I suspected that it is working only for the first time so i changed the name of the service/contract and queue and again tried to test it out it worked that also once it worked. Again I changed the name and tried again it worked once only.
Service Broker Contract/Service/Queue creation
IF NOT EXISTS( SELECT '*'
FROM sys.service_contracts
WHERE NAME = N'TESTContract1234')
BEGIN
CREATE CONTRACT TESTContract1234
([http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer] SENT BY INITIATOR)
END
IF NOT EXISTS( SELECT '*'
FROM sys.service_queues
WHERE NAME = N'TEST_SCHEDULEDJOBQUEUE1234')
BEGIN
create QUEUE TEST_SCHEDULEDJOBQUEUE1234
WITH STATUS = on,
ACTIVATION (
PROCEDURE_NAME = testing1_sp,
MAX_QUEUE_READERS = 1, -- we expect max 20 jobs to start simultaneously
EXECUTE AS 'dbo' );
END
IF NOT EXISTS( SELECT '*'
FROM sys.services
WHERE NAME = N'//TESTJOBSERVICE1234')
BEGIN
CREATE SERVICE [//TESTJOBSERVICE1234]
AUTHORIZATION dbo
ON QUEUE TEST_SCHEDULEDJOBQUEUE1234 (TESTContract1234)
END
SP which gets executed in the Queue
create table testing1
(
descr varchar(255),
seqno int identity(1,1),
currtime date
)
create procedure testing1_sp
as
begin
set nocount on
insert into testing1(descr,currtime) values('Service Broker Sample',getdate())
set nocount off
end
Script used for Testing
declare #ConversationHandle UNIQUEIDENTIFIER ,#TimeoutInSeconds udd_int
SELECT #TimeoutInSeconds = DATEpart(s, dbo.RES_Getdate(0))--, #FirstRunOn);
BEGIN DIALOG CONVERSATION #ConversationHandle
FROM SERVICE [//TESTJOBSERVICE1234]
TO SERVICE '//TESTJOBSERVICE1234',
'CURRENT DATABASE'
ON CONTRACT TESTContract1234
WITH ENCRYPTION = OFF;
At the database level, service broker is enabled I checked the same using sys.databases catalog view column name is_broker_enabled.
In sys.conversation_endpoints catalog view one entry is available and state_desc for the same is "STARTED_OUTBOUND"
Please help me debug the issue and understand where I'm making mistake.
Thanks in advance.

Related

Stored Procedure within Service Broker not able to access another database under same server instance

I have created a service Broker which is executing through Queue formed with the help of Trigger on a table.
I have to call another Database's Stored Procedure/Function from my current database's Queue_Procedure. And when trying to execute it, I am getting below error.
The activated proc '[dbo].[spGenerateProc_Test_RJ]' running on queue
'FirstDatabase.dbo.TestQueue_Test_RJ' output the following: 'The
server principal "sa" is not able to access the database
"SecondDatabase" under the current security context.'
Below is all query in steps I am using to create Service broker Queue and use it.
--Step 1:
Use FirstDatabaseName;
ALTER DATABASE FirstDatabaseName SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE;
--Step 2:
CREATE TABLE PriceData_auditlog_Test_RJ
(
xmlstring xml
)
GO
CREATE PROCEDURE [dbo].[spGenerateProc_Test_RJ]
WITH EXECUTE AS CALLER
AS
BEGIN
DECLARE #message_type varchar(100)
DECLARE #dialog uniqueidentifier, #message_body XML;
WHILE (1 = 1)
BEGIN -- Receive the next available message from the queue
WAITFOR (
RECEIVE TOP(1) #message_type = message_type_name,
#message_body = CAST(message_body AS XML),
#dialog = conversation_handle
FROM dbo.TestQueue_Test_RJ
), TIMEOUT 500
IF (##ROWCOUNT = 0 OR #message_body IS NULL)
BEGIN
BREAK
END
ELSE
BEGIN
--process xml message here...
INSERT INTO PriceData_auditlog_Test_RJ values(#message_body)
SELECT BlobData.dbo.Get_BlobTagsCount_Test_RJ()
END
END CONVERSATION #dialog
END
END
--step 3: Create Message Type
CREATE MESSAGE TYPE TestMessage_Test_RJ
AUTHORIZATION dbo
VALIDATION = WELL_FORMED_XML;
--step 4: Create Contract
CREATE CONTRACT TestContract_Test_RJ
AUTHORIZATION dbo
(TestMessage_Test_RJ SENT BY INITIATOR);
-- step 5: Create Queue
CREATE QUEUE dbo.TestQueue_Test_RJ WITH STATUS=ON, ACTIVATION
(STATUS = ON, MAX_QUEUE_READERS = 7,
PROCEDURE_NAME = [dbo].[spGenerateProc_Test_RJ], EXECUTE AS N'dbo');
-- step 6: Create Service Initiator
CREATE SERVICE TestServiceInitiator_Test_RJ
AUTHORIZATION dbo
ON QUEUE dbo.TestQueue_Test_RJ (TestContract_Test_RJ);
--step 7: Create target Service
CREATE SERVICE [TestServiceTarget_Test_RJ]
AUTHORIZATION dbo
ON QUEUE dbo.TestQueue_Test_RJ (TestContract_Test_RJ);
--Step 8: CREATE Trigger on FirstDatabase table
CREATE TRIGGER [dbo].[Trg_PriceData_Update_Test_RJ]
ON FirstDatabaseName.dbo.Price
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #MessageBody XML
--get relevant information from inserted/deleted and convert to xml message
SET #MessageBody = (SELECT ProductID FROM inserted FOR XML AUTO)
If (#MessageBody IS NOT NULL)
BEGIN
SELECT #MessageBody
DECLARE #Handle UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION #Handle
FROM SERVICE [TestServiceInitiator_Test_RJ]
TO SERVICE 'TestServiceTarget_Test_RJ'
ON CONTRACT [TestContract_Test_RJ]
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION #Handle
MESSAGE TYPE [TestMessage_Test_RJ](#MessageBody);
END
END
GO
--Update statement to fire trigger which executes Service Broker Queue
Update FirstDatabaseName.dbo.Price
SET Price=141.833
WHERE ID=1408166
I have also followed steps mentioned in Blog link
But still I am getting same error.
The activated proc '[dbo].[spGenerateProc_Test_RJ]' running on queue 'FirstDatabase.dbo.BundleQueue_Test_RJ' output the following: 'The server principal "sa" is not able to access the database "SecondDatabase" under the current security context.'
Edit:
By referring link, Below are the steps I have used for creating certificate to use function/Procedure in other database.
Source db configuration
--Certificate Installation Start
-- Create a certificate with a private key
USE [FirstDatabseName]
GO
CREATE CERTIFICATE [spGenerateBundleProcAudit_Test_RJ]
ENCRYPTION BY PASSWORD = 'Password#1234'
WITH SUBJECT = 'spGenerateBundleProcedure Signing for audit certificate';
GO
--Sign the procedure with the certificate’s private key
ADD SIGNATURE TO OBJECT::[spGenerateBundleProc_Test_RJ]
BY CERTIFICATE [spGenerateBundleProcAudit_Test_RJ]
WITH PASSWORD = 'Password#1234';
GO
--Drop the private key. This way it cannot be
-- used again to sign other procedures.
ALTER CERTIFICATE [spGenerateBundleProcAudit_Test_RJ]
REMOVE PRIVATE KEY;
GO
--We must backup to a file and create
--the certificate in [master] from this file
BACKUP CERTIFICATE [spGenerateBundleProcAudit_Test_RJ]
TO FILE = 'C:\spGenerateBundleProcAudit2_Test_RJ.CER';
GO
Target db configuration
USE [SecondDatabseName]
GO
--DROP CERTIFICATE [spGenerateBundleProcAudit_Test_RJ]
CREATE CERTIFICATE [spGenerateBundleProcAudit_Test_RJ]
FROM FILE = 'C:\spGenerateBundleProcAudit2_Test_RJ.CER';
GO
--DROP USER [spGenerateBundleProcAudit_Test_RJ]
CREATE USER [spGenerateBundleProcAudit_Test_RJ]
FROM CERTIFICATE [spGenerateBundleProcAudit_Test_RJ];
GO
--‘AUTHENTICATE’ permission is required for all other permissions to take effect
GRANT AUTHENTICATE TO [spGenerateBundleProcAudit_Test_RJ];
GRANT EXECUTE ON [Get_BlobTagsCount_Test_RJ] TO [spGenerateBundleProcAudit_Test_RJ];
GO
--Enable back the disabled ‘SessionsService’ queue
ALTER QUEUE dbo.TestQueue_Test_RJ WITH STATUS=ON
GO
--Certificate Installation End

Service Broker Internal Activation Poisoning - Where?

I am experiencing poison messages and I am not sure why.
My broker setup looks like this:
CREATE MESSAGE TYPE
[//DB/Schema/RequestMessage]
VALIDATION = WELL_FORMED_XML;
CREATE MESSAGE TYPE
[//DB/Schema/ReplyMessage]
VALIDATION = WELL_FORMED_XML;
CREATE CONTRACT [//DB/Schema/Contract](
[//DB/Schema/RequestMessage] SENT BY INITIATOR,
[//DB/Schema/ReplyMessage] SENT BY TARGET
)
CREATE QUEUE Schema.TargetQueue
CREATE SERVICE [//DB/Schema/TargetService]
ON QUEUE Schema.TargetQueue (
[//DB/Schema/Method3Contract]
)
CREATE QUEUE Schema.InitiatorQueue
CREATE SERVICE [//DB/Schema/InitiatorService]
ON QUEUE Schema.InitiatorQueue
Then I have my internal activation procedure:
CREATE PROCEDURE Schema.Import
AS
DECLARE #RequestHandle UNIQUEIDENTIFIER;
DECLARE #RequestMessage VARCHAR(8);
DECLARE #RequestMessageName sysname;
WHILE (1=1)
BEGIN
BEGIN TRANSACTION;
WAITFOR (
RECEIVE TOP(1)
#RequestHandle = conversation_handle,
#RequestMessage = message_body,
#RequestMessageName = message_type_name
FROM
Schema.TargetQueue
), TIMEOUT 5000;
IF (##ROWCOUNT = 0)
BEGIN
COMMIT TRANSACTION;
BREAK;
END
EXEC Schema.ImportStep1 #ID = #RequestMessage;
--EXEC Schema.ImportStep2 #ID = #RequestMessage;
END CONVERSATION #RequestHandle;
COMMIT TRANSACTION;
END
My activation is enabled by:
ALTER QUEUE Schema.TargetQueue
WITH
STATUS = ON,
ACTIVATION
( STATUS = ON,
PROCEDURE_NAME = Schema.Import,
MAX_QUEUE_READERS = 10,
EXECUTE AS SELF
)
I initiate this process with this stored procedure
CREATE PROCEDURE Schema.ImportStart
AS
BEGIN
DECLARE #ID VARCHAR(8);
DECLARE Cursor CURSOR FOR
SELECT ID FROM OtherDatabase.OtherSchema.ImportTable
EXCEPT
SELECT ID FROM Table
OPEN Cursor;
FETCH NEXT FROM Cursor INTO #ID;
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #InitiateHandle UNIQUEIDENTIFIER;
DECLARE #RequestMessage VARCHAR(8);
BEGIN TRANSACTION;
BEGIN DIALOG
#InitiateHandle
FROM SERVICE
[//DB/Schema/InitiatorService]
TO SERVICE
N'//DB/Schema/TargetService'
ON CONTRACT
[//DB/Schema/Contract]
WITH
ENCRYPTION = OFF;
SELECT #RequestMessage = #ID;
SEND ON CONVERSATION
#InitiateHandle
MESSAGE TYPE
[//DB/Schema/RequestMessage]
(#RequestMessage);
COMMIT TRANSACTION;
FETCH NEXT FROM Cursor INTO #ID;
END
CLOSE Cursor;
DEALLOCATE Cursor;
END
So how this should work is:
I execute ImportStart
A message for each ID gets generated
Internal activation makes Import steps execute
Instead, I get poison messaging and the queue becomes disabled.
If however,
I I set Schema.TargetQue Activation to OFF
EXEC schema.ImportStart
EXEC schema.Import manually
It works fine.
Any insights anyone?
Well:
Your message types are defined as well_formed_xml, yet you send varchar(8) as a message body. Does it really work?
You use [//DB/Schema/Method3Contract] for the target queue, but do not define it. A misspelling, most likely.
You specify EXECUTE AS SELF in the queue activation. BOL says some mystical thing about this case:
SELF
Specifies that the stored procedure executes as the current user. (The database principal executing this ALTER QUEUE statement.)
I'm not really sure I understand the quoted statement, because it apparently contradicts with your experience. If it would be your user account, everything should have been fine, because you seem to have all permissions necessary to do the job.
So, just in case - who is the owner of the Schema schema? What permissions does this principal possess? And, if it's not you, who executes the alter queue statement (and why)?
Without access to logs, it's significantly more difficult to diagnose the problem, but I would start with creating a new user account with permissions identical to yours, setting it the owner of the Schema schema and then slowly working it down, revoking unnecessary permissions until it breaks. Assuming, of course, it will work at all.

Untrusted security context in signed activated procedure

I have an activated procedure for a service broker queue that queries a linked server. I have signed the procedure using the method found here. However, I continuously see the following message in the sql server logs:
The activated proc '[dbo].[TestProc]' running on queue 'DBName.dbo.TestReceiveQueue' output the following: 'Access to the remote server is denied because the current security context is not trusted.'
The strange thing is that I have several different activated procedures in the same database, signed by the same certificate, that also do linked server queries, and work fine. For some reason, this procedure refuses to.
Here's some code to (mostly) reproduce the problem. I've created the certificate and associated login already.
CREATE PROCEDURE TestProc
WITH EXECUTE AS OWNER
AS
BEGIN
SET NOCOUNT ON;
DECLARE #convHandle UNIQUEIDENTIFIER;
DECLARE #msgTypeName SYSNAME;
DECLARE #status TINYINT;
DECLARE #srvName NVARCHAR(512);
DECLARE #srvConName NVARCHAR(256);
DECLARE #msgTypeValidation AS NCHAR(2);
DECLARE #msgBody NVARCHAR(256);
DECLARE #cmd AS NVARCHAR(50);
RECEIVE TOP(1)
#convHandle = conversation_handle,
#msgTypeName = message_type_name,
#status = status,
#srvName = service_name,
#srvConName = service_contract_name,
#msgTypeValidation = validation,
#msgBody = CAST(message_body AS NVARCHAR(256))
FROM TestReceiveQueue;
--SELECT #convHandle, #msgBody
IF (##ROWCOUNT != 0)
BEGIN
SELECT * FROM openquery(LINKEDSERVERNAME, 'SELECT * FROM LINKEDSERVERDB.SCHEMA.TABLE')
END CONVERSATION #convHandle
END
END
GO
CREATE MESSAGE TYPE [TestMessageType] VALIDATION = NONE;
CREATE CONTRACT TestContract (TestMessageType SENT BY INITIATOR)
CREATE QUEUE [dbo].[TestReceiveQueue] With STATUS = ON, RETENTION = OFF, ACTIVATION (STATUS = ON, PROCEDURE_NAME = [dbo].[TestProc], MAX_QUEUE_READERS = 1, EXECUTE AS OWNER ), POISON_MESSAGE_HANDLING (STATUS = OFF) ON [PRIMARY]
CREATE QUEUE [dbo].[TestSendQueue] WITH STATUS = ON, RETENTION = OFF, POISON_MESSAGE_HANDLING (STATUS = OFF) ON [PRIMARY]
CREATE SERVICE [TestReceiveService] ON QUEUE [dbo].[TestReceiveQueue] (TestContract)
CREATE SERVICE [TestSendService] ON QUEUE [dbo].[TestSendQueue] (TestContract)
Drop Procedure TestProc
ADD SIGNATURE TO OBJECT::[TestProc]
BY CERTIFICATE [ServiceBrokerProcsCert]
WITH PASSWORD = 'PASSWORDHERE'
GO
Is there any way I can debug this further, to figure out why I'm getting this error? I've tried ssbdiagnose on the conversation and there aren't any configuration errors. I also tried logging the CURRENT_USER inside the activated sproc which came back as dbo.
When I mark the database as trustworthy, it works, of course (but that's what I'm trying to avoid).
If database is TRUSTWORTHY OFF procedure will run only in context of signing user, not its OWNER as you expect.
Assign linked server privileges to user assiociated with ServiceBrokerProcsCert, it is right user in which context signed activation procedure runs.

SQL broker queue is populating twice

I am using SQL broker to do some asynchronous tasks(In my case sending mails). But the problem I am having is the stored procedure which is run when the the value is inserted to the queue runs twice every time the XML message is passed from a Trigger to the queue.
I have a message type:
CREATE MESSAGE TYPE MailMessage
AUTHORIZATION dbo
VALIDATION = WELL_FORMED_XML
I have a contract:
CREATE CONTRACT MailContract
AUTHORIZATION dbo
(MailMessage SENT BY INITIATOR)
I have a Queue:
CREATE QUEUE dbo.MessageQueue
WITH STATUS=ON,
ACTIVATION (
PROCEDURE_NAME = MailExecuter ,
MAX_QUEUE_READERS = 1,
EXECUTE AS OWNER );
I have two services:
CREATE SERVICE MailSendActivator
AUTHORIZATION dbo
ON QUEUE dbo.MessageQueue (MailContract) ; // I have removed this the contract to make it a initiator but it did not worked out
-- Create target Service
CREATE SERVICE MailSendExec
AUTHORIZATION dbo
ON QUEUE dbo.MessageQueue (MailContract);
Here is my trigger:
CREATE TRIGGER MailSendTrigOnMailQueue ON dbo.MailQueue
FOR INSERT
As
SET NOCOUNT ON;
DECLARE #MessageBody XML
DECLARE #TableId int
SET #MessageBody = (SELECT CreatedDateTime,[Subject], MailType FROM inserted
FOR XML AUTO)
If (#MessageBody IS NOT NULL)
BEGIN
DECLARE #Handle UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION #Handle
FROM SERVICE MailSendActivator
TO SERVICE 'MailSendExec'
ON CONTRACT MailContract
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION #Handle MESSAGE TYPE MailMessage(#MessageBody);
END
I have a stored procedure:
In the stored procedure I am Inserting values to a test table whether the stored procedure is running.
Stored Procedure:
CREATE PROCEDURE dbo.MailExecuter
AS
BEGIN
DECLARE #msgBody XML
DECLARE #dlgId uniqueidentifier
Insert into TestTable(Name, Test) values('MEX','test');
WHILE (1 = 1)
BEGIN
WAITFOR ( RECEIVE TOP(1) #msgBody = CAST(message_body AS XML), #dlgId = conversation_handle FROM dbo.MessageQueue ), TIMEOUT 500
IF (##ROWCOUNT = 0 OR #msgBody IS NULL)
BEGIN
BREAK
END
ELSE
BEGIN
DECLARE #Subject nvarchar(200), #CreatedDateTime datetime, #MailType nvarchar(50)
---EXEC dbo.SendMails 1,1;
END
END CONVERSATION #dlgId
END
END
But the stored procedure is running twice and populate my test table twice. I think the problem is with the send conversation part in the trigger.
I have been struck on this for a long time. Please, Can some one help me on this
You need to add to the RECEIVEprojection list the message_type_name. You must look at what message type you received and only call the mailing routine when the message type is MailMessage. As things are, you will always get a second message, the one from your END DIALOG. You simply need to call END DIALOG again on that case, to close the sending side handle:
WAITFOR (
RECEIVE TOP(1)
#msgBody = CAST(message_body AS XML),
#dlgId = conversation_handle ,
#msgType = message_type_name
FROM dbo.MessageQueue ), TIMEOUT 500
IF (##ROWCOUNT = 0 OR #msgBody IS NULL)
BREAK
ELSE IF #msgType = N'MailMessage'
BEGIN
DECLARE #Subject nvarchar(200), #CreatedDateTime datetime, #MailType nvarchar(50)
---EXEC dbo.SendMails 1,1;
END
END CONVERSATION #dlgId;
Any particular reason you are re-inventing the wheel? This is pretty much how sp_send_dbmail already works (except is using external activation).

SQL Server 2008 insert trigger not firing

I have an INSERT trigger on a table that simply executes a job.
Example:
CREATE TABLE test
(
RunDate smalldatetime
)
CREATE TRIGGER StartJob ON test
AFTER INSERT
AS
EXEC msdb.dbo.sp_start_job 'TestJob'
When I insert a record to this table, the job is fired of without any issue. There are a few people, however, that have lower permissions than I do (db_datareader/db_datawriter on the database only); they are able to insert a record to the table, but the trigger does not fire.
I am a SQL Server novice and I was under the impression that users did not need elevated permissions to fire off a trigger (I thought that was one of the big benefits!). Is this a permission issue at the trigger level, or at the job level? What can I do to get around this limitation?
The trigger will execute in the context of the caller, which may or may not have the permissions to access msdb. That seems to be your problem. There are a few ways to extend these permissions using Execute As; they are greatly detailed in this link
Use impersonation within trigger:
CREATE TRIGGER StartJob ON test
with execute as owner
AFTER INSERT
AS
EXEC msdb.dbo.sp_start_job 'TestJob'
And set database to trustworthy (or read about signing in above link):
alter database TestDB set trustworthy on
Another way to go (depending on what operations the agent job performs) would be to leverage a Service Broker queue to handle the stored procedure activation. Your users' context would simply call to Send On the queue while, in an asynchronous process SvcBroker would activate a stored procedure which executed in context of higher elevated user. I would opt for this solution rather than relying on a trigger calling an agent job.
I wanted to test the call to Service Broker, so I wrote this simple test example. Instead of calling an SSIS package I simply send an email, but it is very similar to your situation. Notice I use SET TRUSTWORTHY ON at the top of the script. Please read about the implications of this setting.
To run this sample you will need to substitute your email profile info below, <your_email_address_here>, etc.
use Master;
go
if exists(select * from sys.databases where name = 'TestDB')
drop database TestDB;
create database TestDB;
go
alter database TestDB set ENABLE_BROKER;
go
alter database TestDB set TRUSTWORTHY ON;
use TestDB;
go
------------------------------------------------------------------------------------
-- create procedure that will be called by svc broker
------------------------------------------------------------------------------------
create procedure dbo.usp_SSISCaller
as
set nocount on;
declare #dlgid uniqueidentifier;
begin try
-- * figure out how to start SSIS package from here
-- for now, just send an email to illustrate the async callback
;receive top(1)
#dlgid = conversation_handle
from SSISCallerQueue;
if ##rowcount = 0
begin
return;
end
end conversation #dlgid;
exec msdb.dbo.sp_send_dbmail
#profile_name = '<your_profile_here>',
#importance = 'NORMAL',
#sensitivity = 'NORMAL',
#recipients = '<your_email_address_here>',
#copy_recipients = '',
#blind_copy_recipients = '',
#subject = 'test from ssis caller',
#body = 'testing',
#body_format = 'TEXT';
return 0;
end try
begin catch
declare #msg varchar(max);
select #msg = error_message();
raiserror(#msg, 16, 1);
return -1;
end catch;
go
------------------------------------------------------------------------------------
-- setup svcbroker objects
------------------------------------------------------------------------------------
create contract [//SSISCallerContract]
([http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer] sent by initiator)
create queue SSISCallerQueue
with status = on,
activation (
procedure_name = usp_SSISCaller,
max_queue_readers = 1,
execute as 'dbo' );
create service [//SSISCallerService]
authorization dbo
on queue SSISCallerQueue ([//SSISCallerContract]);
go
return;
-- usage
/*
-- put a row into the queue to trigger the call to usp_SSISCaller
begin transaction;
declare #dlgId uniqueidentifier;
begin dialog conversation #dlgId
from service [//SSISCallerService]
to service '//SSISCallerService',
'CURRENT DATABASE'
on contract [//SSISCallerContract]
with encryption = off;
begin conversation timer (#dlgId)
TIMEOUT = 5; -- seconds
commit transaction;
*/
It would be permissions at the job level. You can possibly assign those users the SQLAgentReaderRole in MSDB to be able to start a job, considering that they would be added to a group that owned the job. If they are not in a group which owns the job, it gets more difficult.

Resources