I want to push data to Excel from a restricted table.
I've created a view and pull the data from the table, now an Excel account has been granted to access the view but still can't get the data.
What's the best option here,
owner access option, if possible at all in SQL Server (making the view run as dbo, even when called from Excel user) - may be counter-security
Stored procedure?
regards,
The stored procedure drove me all the way home.
Related
Is there a way to lock down (preferably at the server level but DB level is also fine) tables and stored procedures? I don't want specific users creating new procedures or tables, but want them to be able to write to tables (via some Excel macros we have in place) and execute existing procedures. I would not want this to be a blanket policy, I'd prefer to specify which users this applies to.
Do you have individual ms SQL server logins for every user? Then you can set the access rights of these to Datareader and datawriter only in the security section or on database level.
If everyone uses the same login, you will have to create trigger on the data definition level. E.g. a trigger on CREATE TABLE that aborts any action.
Edit: I suggest you create a new login specifically for those excel macros.
What I need is to create stored procedure inside non master database that will create login and user based on data in database.
It works in SQL Server, but is it possible to do it in Azure SQL Database?
No, it's impossible.
In SQL Database, you must be connected to the master database to create a login.
Please reference: SQL Database Logins.
That means even you have create the stored procedure inside non master database, when you execute it, you may get the error like:
Hope this helps
I'm tired of searching for this, but I couldn't find anything.
I have three databases in SQL Server and although all stored procedures are in the Main database, they work with tables from the other databases.
My question is: if you have the query
select name
from SecondDatabase.dbo.SomeTable
where id = 56
and this query is stored in the main database, will it run in the main database and go all the way to the second database and returns the data, or will it run in the second database and you have the select result directly?
(hope you understand my question)
I think you are misunderstanding the difference between a Database and an Instance.
An instance is the software running the SQL service. Each instance can have multiple databases. For example, there is a master database and a tempdb database for each instance of SQL Server, these are system databases. You can create any number of user databases. All these databases will be handled by the same SQL Server instance (on the same machine).
A particular client session is connected first to an instance and then to a particular database, thats why you include which database you will connect to by default on connection strings (or by login). When you write select name from SecondDatabase.dbo.SomeTable, you are telling the SQL service to retrieve data from the SecondDatabase, even if your session is linked to any other database. The engine will then use your login credential to match a user of the other database (since users go by database and logins by instance) to validate if it has enough privileges to query that table, before searching for the data.
A complete different story would be trying to access data from another instance (machine), in which you will need a linked server, a openrowset or such.
use FirstDatabase
select name
from SecondDatabase.dbo.SomeTable
where id = 56
Question:
will it run in the main database and go all the way to the second
database and returns the data, or will it run in the second database
and you have the select result directly?
Your first assumption is correct:
This query will run in a first database, it will use context and all settings (ANSI, query optimizer and statistic related) of the first database but will get data from a table of the second database.
Just an example from a life: if database have to stay in an old compatibility mode, but new T-SQL features need occasionally to be used, query can switch context to tempdb (which normally set to the latest compatibility level) and run queries referencing data from any other database where access is granted. Usage of those new features will not raise exception
The (now edited) query above will always execute on SecondDatabase.dbo.SomeTable even if the active database context was another database and even if the active user had a different default schema. This is because the object SomeTable is qualified with the schema and the schema owner.
Test to illustrate that the following still returns the executed results (assuming the objects exist and the active user context has access to them)
USE [OtherDatabaseSchema]
GO
SELECT TOP 10 *
FROM [SecondDatabase].[dbo].[SomeTable]
I'm trying to implement security on our applications (which consist mainly of websites using SQL Server stored procedures).
Microsoft seem to suggest that best practice is to wrap all data functionality in stored procedures which we have done. Our structure is something like:
SQL Server database - [data1]
SQL Server database - [webSPs]
PHP / Symfony web apps
All the data resides in tables in [data1] and on the same server is another 'database' which just contains the stored procedures used by the web apps.
The SQL Server has a login 'webapp' which, as a user on [webSPs], has permissions just to run the stored procedures in [webSPs].
However, as these stored procedures read, write, append data on the [data1] tables, this user has to be a member of db_datawriter and db_datareader database roles in [data1].
This all works fine, but it seems there is a hole in the security here, as its then possible for a user accessing [webSPs] to not only run the stored procedures but write to any underlying table - is it possible to give permission that say something like:
you can read/write to tables on this database but only through SPs - not directly
From what I've read, I think it would work as I hoped if there wasn't the second database which I guess is breaking ownership chaining.
Thank you in advance.
Yes, but it's frankly a pain to implement. You can use module signing. Essentially, you:
Create a certificate in your WebSps database.
Backup and restore the certificate to the data1 database
Create a user from the certificate
Grant whatever read and write permissions to the certificate-based user in data1
Sign any stored procedure you want to use cross-database with the certificate by calling the add signature syntax
Keep in mind that every time that you change the procedure (either via alter or drop and create), the signature gets lost. So you'll be in a constant cycle of re-signing. You can read more about the process of module signing here
I have a stored procedure that updates data in a table for a specific record. I have several users who will be making use of this stored procedure however I only want to them to be able to update records that are assigned to them.
Each record that is to be updated by the stored procedure has a field named "UserID" which define who has control over the record. I also have a mapping table that maps active directory logins to the UserID's.
I am using Active Directory so SQL Server knows who is attempting to execute the stored procedure. Is there a way within the stored procedure to look-up the users active directory login in another table and then determine if they have access to the records attempting to be updated?
You can find out who the current user is in the proc by calling SYSTEM_USER and incorporating that into the query that updates the rows.
Does this article help? Granting Row-Level Permissions in SQL Server
It recommends the following steps
Create the table, adding an additional column to store the name.
Create a view that has a WHERE clause based on the user name column. This will restrict the rows returned to those with the specified value. Use one of the built-in functions to specify a database user or login name. This eliminates the need to create different views for different users.
Create stored procedures to select, insert, update, and delete data based on the view, not the base tables. The view provides a filter that restricts the rows returned or modified.
For stored procedures that insert data, capture the user name using the same function specified in the WHERE clause of the view and insert that value into the UserName column.
Deny all permissions on the tables and views to the public role. Users will not be able to inherit permissions from other database roles, because the WHERE clause is based on user or login names, not on roles.
Grant EXECUTE on the stored procedures to database roles. Users can only access data through the stored procedures provided.
I'm no application designer but on the surface, your solution sounds unnecessarily complicated to me.
That said, you can issue the following query to get the Windows AD Login name of the user currently executing the stored procedure. You can use this information to cross reference with your mapping table to determine if the AD account has the required privileges to perform the operation.
SELECT SYSTEM_USER
Do keep in mind that this returns the name of the currently executing context, so keep in mind that this can be explicitly changed using the "Execute As" statement.
EDIT:
I wonder if perhaps a view could be used to limit the data visible to a given AD account. The Stored Procedure logic could then focus on the data modification aspect, rather than security implementation. Controlling your data access using views would also ensure that a consistent security access method is used across multiple stored procedures if required, as opposed to having to implement security checking within each.
Since writing this, the link provided by Martin Smith, details how this solution can be implemented:
Granting Row-Level Permissions in SQL Server
In conclusion, a combination of both is how Microsoft suggest you implement the solution to your problem.