Azure Data Factory pipelines confuse accounts for DB access - sql-server

We faced the following problem:
In the same data factory we have pipeline A and pipeline B. They include Copy Data Activity (A and B). Each Copy Data Activitie linked to different Data Sets (A and B) and different SQL Linked Services (A and B) with different service accounts (A and B). All Linked Services use the same Integration Runtime (IR) to connect on premise database.
A and B Activities run Stored procedure A and B. Service account A have execute permission
for procedure A and service account B for procedure B (obviously).
But when pipelines A and B get started at the same time by timer trigger we have errors:
[The EXECUTE permission was denied on the Stored procedure 'A'] in pipeline A log and [The EXECUTE permission was denied on the Stored procedure 'B'] in pipeline B log.
When we stoped one of time triggers for each pipelines, to avoid parallel execution, everything worked fine!
I believe pipelines A and B confuse accounts in some way.
Does anyone know how to check and fix it?

It seems like the two pipelines are trying to use the same resources at the same time, due to which you are getting error.
Please try the below solutions to resolve the issue.
In the same pipeline, you can run Pipeline A and Pipeline B in sequence. Arrange the activities in the pipeline A to run. At the end pipeline A, add the Execute Pipeline activity to run the Pipeline B.
You can create a custom "executor" role and new user, then grant execute permissions to it. Now use this user credentials in your Pipeline B Linked Service to access the database.
In your master DB, first create a new user:
CREATE USER MyUser FOR LOGIN MyLogin WITH DEFAULT_SCHEMA=[dbo]
GO
Then, in your new DB:
CREATE ROLE [db_executor] AUTHORIZATION [dbo]
GO
GRANT EXECUTE TO [db_executor]
GO
sp_addrolemember #rolename = 'db_executor', #membername = 'MyUser'

Related

Limit authorization into SQL Server for stored procedure - only calls

In order to keep my database's data integrity, I am trying to unauthorize all the queries that aren't calls to a stored procedure. But I don't want queries that I run directly from SQL Server to be blocked because then I will be unable to make any changes to the database (If the database cannot differentiate between "inside" queries and "outside" queries, maybe queries will be allowed under a particular authorization). How can I do such a thing?
You need to create a custom application role in your database that can only execute those stored procedures - but doesn't have any permissions to read or update data directly.
The simplest approach I usually take is this:
Create a custom database role db_executor which works similar to db_datareader
Grant this role the permission to execute all current and future stored procedures
Create users that only get this role - these users can connect to your database and they can only execute stored procedures - nothing else
Step 1 - create new role
CREATE ROLE [db_executor]
Step 2 - grant permissions
GRANT EXECUTE TO db_executor;
This grants the permission to execute any stored procedures in this database - and the great thing is: this doesn't apply to just the stored procedures that exist at the time you run this - this will also include any stored procedures you might create in the future
Step 3 - add user(s) to this role
You can do this in the GUI of course - or using this T-SQL:
ALTER ROLE [db_executor] ADD MEMBER [your-user-name-here]

How to create a login that ONLY has access to run stored procedures?

I have a C# Winform application that interacts with an SQL Server DB via stored procedures. In SSMS, how do I create a login that ONLY has permissions to run stored procedures? That login wouldn't be able to view/edit/create table definitions, etc. It would also only have access to a single specified DB.
The reason I want to create such a login is because I store the SQL Server credentials used by my Winform application in its App.config file. Since the app.config can easily be read, anyone with malicious intent can easily perform unwanted operations on the database if the given login had any other permissions than just stored procedures.
A neat trick in this scenario is to create a separate (custom) SQL Server role that can only execute stored procedures:
CREATE ROLE db_executor;
GRANT EXECUTE TO db_executor;
This role now has the permission to execute any stored procedure in the database in which it's been created - and in addition: that permission will also extend to any future stored procedures you might create later on in this database.
Now create a user in your database and give it only this database role - this user will only be able to execute stored procedures - any and all of them in your database.
If you user should be allowed to execute any and all stored procedures - this is a very convenient way to allow this (and you don't have to constantly update the permissions when new stored procedures are created).
You can use the following query in order to allow stored procedure execute permision to your user
USE [DB]
GRANT EXECUTE ON dbo.procname TO username;
However, in my humble opinion , you should secure the connection string in the app.config.
Maybe , this How to store login details securely in the application config file link can be helped to you.
The access to a specific database is done through creating a user on the database that you want him to operate on. You can find more infos about users here.
If the user is created you can Grant, With Grant and Deny actions for every single item on the database.
The user will then be granted/denied those rights by a grantor, which is the dbo by default.
You can use this to also deny him access to every item on your database that isn't your stored procedure, which is what you're looking for if I understand you correctly.
Try folloiwng approach (grant execute should be repeated for every SP). Note that MyStoredProcedure has to be in MyDatabase :)
-- create login to server
create login test_user with password = 'test';
-- create user mapped to a database
use MyDatabase
go
create user test_user for login test_user;
-- grant permission to execute SP
grant execute on MyStoredProcedure to test_user

permission in SP

I have my sql auth user, which has Insert access to table A in database A.
I have my team’s sql user, which has read access to table B in database B.
I need to create a SP, that will select from table B in database B and insert it in table A in database A. (and should run daily …)
What’s the most professional approach? I don’t want to use EXECUTE AS…
I also don’t understand… if the SP by default gets executed with the caller’s permission, the caller would be sql agent, so in the SP I could be dropping all the databases?! (what am I missing?)
if it gets executed with the creator permissions, is it executed with the creators permission at the moment of creation or at the current moment of execution?!
I'll tell you how I do similar things currently. We will have a Active Directory service account set up with the needed access, be it DBO, sys admin or data Writer. Create a job to run the script in question and the Job will use the SQL Agent's user ID or whatever account you designate.
Our SQL agent account has the needed permissions to run any jobs that are needed on the server and works the easiest for us. You only have to set it up once and then use that account for all jobs.

Service broker - Cross-database SELECTs to insert into local DB?

I'm using Remus' article http://rusanu.com/2006/03/07/call-a-procedure-in-another-database-from-an-activated-procedure/ as a guide.
What I'm trying to do:
I have a Activated Stored Procedure that (within the Activated SP) calls 2 different stored procedures. One of those stored procedures needs to access tables in another database to lookup some data, after which it writes the record locally with the extra info. Since I'm crossing databases, my options are
"trustworthy" (pass, thanks)
"replicate lookup tables to the same database service broker is in"
"get certificates working" (this approach)
So I did the following, but it's still failing with "lock time out exceeded" and "not able to access database... under the current security context.
In the database service broker is running in:
USE database_with_service_broker_and_queue
GO
CREATE CERTIFICATE mysp_Auditing ENCRYPTION
BY PASSWORD = '123457'
with subject = 'god_i_hope_this_works'
ADD SIGNATURE TO OBJECT::myschema.mystoredprocedure
BY CERTIFICATE mysp_Auditing
WITH PASSWORD = '123457'
ALTER CERTIFICATE mysp_Auditing REMOVE PRIVATE KEY
BACKUP CERTIFICATE mysp_Auditing to file = 'c:\mysp_auditing.CER'
Now in the database with the additional tables:
USE db_with_tables_I_need
GO
CREATE CERTIFICATE mysp_Auditing from file = 'c:\mysp_auditing.CER'
CREATE USER mysp_Auditing FROM CERTIFICATE mysp_Auditing
GRANT AUTHENTICATE to mysp_Auditing
GRANT SELECT ON TABLE1 to mysp_Auditing
GRANT SELECT on TABLE2 to mysp_Auditing
I then ENABLE the queue and watch alllll the error messages scroll by. I even tried changing the stored procedure to add EXECUTE AS OWNER, but still doesn't work.
Any help appreciated.
too long to post as comment
not able to access database... under the current security context.
This means the certificate business is not set up correct (I don't blame you, is ungodly hard to pull it off on first try). I would look at these:
make sure 'dbo' is a valid user. Try running EXECUTE AS USER='dbo'; on both DBs involved. If one fails (it means the DB was created by a Windows SID that is no longer valid) run ALTER AUTHORIZATION ON DATABASE:<dbname> TO sa.
make sure you do not change the procedure after you sign it. Any ALTER will silently drop the signature and invalidate your trust chain.
add EXECUTE AS OWNER
The procedure must have an EXECUTE AS clause, but it should not matter much what it is, as long as there is one. You are granting the SELECT permission to the certificate (hence to the signature) so it should work no matter who the procedure impersonates.
For debugging, I recommend you do it by simply running the stored proc manually, from SSMS query window:
USE myactivateddb;
GO
EXECUTE AS USER='dbo'; -- does not matter who, is important to be AS USER
GO
EXEC myotherdb.dbo.myotherproc ...;
GO
REVERT;
GO
This is easier to debug that trying to do it from activated procedure. If this works, then try the same but instead of executing the other DB stored proc, execute the activated procedure from the SSMS query window (w/o truning on activation on the queue).
Looks like metadata lock. If you do any DDL in your activation procedure, like creating an index or manipulating columns, you can expect lock timeouts if multiple instances of activation procedure are in service. Remember that activation procedure is typically a long running transaction, and if it takes a lock on any object, it keeps it locked until the end of transaction.

Transact-SQL Job permission

I have 2 SQL servers: A & B. On A, I have a stored proc that processes some data from B and then dumps the results into a table on A. I need to schedule a job to run this proc.
According to http://msdn.microsoft.com/en-us/library/ms189064(SQL.105).aspx, it's the Job Owner that gets used when running the job. (Can't set a "Run as" on the job step for TSQL step/job.)
How the network people have set these machines / security up for is to use a third server, C, with centralised logins stored on that. So my login is: SERVERC\SEAN. This login has access to both DB servers, A & B. The proc runs fine if I execute when logged in and connected to Server A.
So I set the job owner as SERVERC\SEAN, but when the job runs, the error message is:
"Executed as user: NT AUTHORITY\NETWORK SERVICE. Login failed for user SERVERC\SERVERA$"
Why is it running as Network Service, and some weird login combination, instead of as the job owner, as instructed? How do I get this to work?
Thanks
Check out this post, it should do what you want it to.
Editing to show most helpful link
http://social.msdn.microsoft.com/Forums/en/sqltools/thread/54dff132-b9c9-4753-b0c5-2134bf7f4327

Resources