Permission to execute (actually SELECT) a user defined function to EVERYONE - sql

We have created a UDF, now this fetched information from some restricted database(s) and also reads extended properties of restricted database(s). We wish to keep restricted database(s) as is, i.e. that is no direct access to those databases.
However, we would like everyone (I mean every authenticated SQL user) to be able to run this scaler UDF like this:
SELECT somedatabase.dbo.udf_getInfo()
So in other words, only scaler function udf_getInfo should be accessible to everyone, and this scaler value function will read some DB information, that user executing have no direct access.

use YourDbName
GO
-- only one of these is correct
GRANT SELECT on dbo.udf_getinfo() TO public
GO
-- only one of these is correct
GRANT EXEC on dbo.udf_getinfo() TO public
GO
-- YOU MUST HAVE PERMISSION also - AND - you need to have the GRANT on it to give the permission.

Related

Is it possible to allow a user to call a BigQuery UDF but not see its definition?

I have a BigQuery User Defined Function (UDF) in which the definition contains a secret:
CREATE FUNCTION mydataset.HashWithPepper(input STRING, y INT64)
RETURNS STRING
AS SHA256(input + "secret_value_acting_as_a_pepper");
secret_value_acting_as_a_pepper is being used to pepper the inputted value. That value is a secret and cannot be known by people using the function.
Is it possible to grant someone permission to call a UDF but not see the definition of it? I've looked at https://cloud.google.com/bigquery/docs/access-control#bq-permissions and noted the following:
Permission
Description
bigquery.routines.get
Get routine definitions and metadata.
So clearly I do not want to grant bigquery.routines.get to my end-users, but how do I grant permission to call the UDF? I don't see a permission in bigquery.routines.* that pertains to calling a UDF.
I do not believer there is a way to hide the UDF definition from anyone allowed to call the routine.
BigQuery does support authorized UDFs which work much like authorized views. An authorized UDF can read data from BigQuery tables without needed to grant callers access to the tables directly.
One possible solution leveraging an authorized UDF would be:
Create a PEPPER table to hold your pepper value in dataset A.
Create the UDF that selects the pepper value from the PEPPER table and uses it with the hash function. Create the UDF in database B.
Declare the UDF an authorized UDF of dataset A.
Grant users BigQuery Data Viewer privileges to dataset B. Do not grant users any access to dataset A.

SQL Server - Creating User Defined Table Type - Creating User Does not have Execute Permission?

I don't think this is a replica question - I've seen the other responses to questions of a similar nature here:
The EXECUTE permission is denied on the user-defined table types?
Table valued parameter in a stored procedure gets execute permissions denied error
My question is - how come when I create a User-Defined Table Type with a user, why does that user not have execute permission on it?
For example, I'm logged in with user myuser, using this user I create a UDT, and a stored procedure that uses the UDT. With the same user, I then try to execute the procedure, but get the error
'The EXECUTE permission was denied on the object 'MyUdt', database 'MyDb', schema 'dbo'.'
Now, I would assume that since it's the same user that created the UDT, this would automatically have the right permissions on it? You cannot use the GRANT EXECUTE command as suggested in the above posts, as you cannot grant permissions to yourself.
In summary - I wish to create a UDT, a procedure that uses it and be able to execute it all using the same user - why am I unable to do this? Am I missing something?
Sounds like you are being a victim of Ownership and User-Schema Separation in SQL Server:
By default, when developers create objects in a schema, the objects are owned by the security principal that owns the schema, not the developer.
Even though you've been granted permission to create an object, the object it belongs to the owner of the schema into which you created the object (dbo schema). Knowing what the problem is, you can settle on one of the several possible solutions (eg. use your own schema rather than dbo, transfer the ownership explicitly, use code signing etc).

odbc32 and SQLBrowseConnect Help

I'm making a call to odbc32.dll (SQLBrowseConnect) to return a list of databases on a sql server.
From running a trace I can see the query being executed is
select name from master..sysdatabases where has_dbaccess(name)=1
If the credentials I pass aren't the sa user it returns just the system databases. Is there anyway I can use SQLBrowseConnect with another user (whose default database is also not guarenteed to be the master database) to return all databases on the server?
Also I want to avoid smo objects
The query does work without sysadmin credentials.
You need to ensure that you / the credentials you are using are at least in the public database role on each of the databases that you need to connect to.
As you would guess, select name from master..sysdatabases returns all database names irrespective of your access to the DB.

SQL Server user name functions

Consider this T-SQL:
CREATE USER my_test_user WITHOUT LOGIN;
SELECT USER_NAME(), USER, SUSER_SNAME(),SYSTEM_USER, suser_name();
EXECUTE AS USER = 'my_test_user' WITH NO REVERT;
SELECT USER_NAME(), USER, SUSER_SNAME(),SYSTEM_USER, suser_name();
I'm looking at using these accounts WITHOUT LOGIN for auditing purposes. Basically, my "get a database connection" code returns a connection on which the EXECUTE AS USER...WITH NO REVERT has already been executed.
The problem is that I can't get consistent results from any of these user name functions. The two lines of output are:
dbo dbo original_user original_user original_user
my_test_user my_test_user S-1-9-3-XXXXX.. S-1-9-3-XXXXX.. S-1-9-3-XXXXX..
The USER functions produce correct output AFTER the 'EXECUTE AS', but beforehand they're showing dbo rather than the user name
The SUSER functions are just the opposite -- they're correct initially but after impersonation they're showing some sort of ID
The MSDN docs for SUSER_SNAME explicitly give an example where this is supposed to work.
UPDATE: What I'm looking for is a function that will produce 'original_user' in the first case and 'my_test_user' in the second.
Update: you need the ORIGINAL_LOGIN fn here too
Original:
Afterwards, there is no matching system level user. So, it can't resolve the database level sid, so it simply returns the sid from sys.database_principals
CREATE USER my_test_user WITHOUT LOGIN;
SELECT USER_NAME(), USER, SUSER_SNAME(),SYSTEM_USER, suser_name();
EXECUTE AS USER = 'my_test_user' WITH NO REVERT;
SELECT USER_NAME(), USER, SUSER_SNAME(),SYSTEM_USER, suser_name(),
SUSER_SID();
SELECT * FROM sys.database_principals WHERE sid = SUSER_SID();
I don't know if this is by design, but it explains where the number comes from. The rest is as expected as explained below
Notes:
You'll get dbo for USER_NAME() because you are logged on with sysadmin rights. Everyone with "sysadmin" is dbo when using db level user functions.
After changing user context, db level user functions resolve to the database user context
For system level user functions, you'll get the login you used before
Users without login are a special case used exclusively for service broker security (remote service bindings) or for code signing. They represent identity, not impersonation. Do not use users without login for EXECUTE AS. You'll run into all sort of edge cases because they explicitly don't have a user to login mapping and almost everywhere a mapping is expected.
Just a guess here, but it looks like to me that the first select is being run as the user you're currently logged into as with the connection, and in the second select you are then telling sql server to execute as the newly created user.

Stored Procedure Ownership Chaining

I have several stored procedures in my database that are used to load data from a datamart that is housed in a separate database. These procedures are, generally, in the form:
CREATE PROCEDURE load_stuff
WITH EXECUTE AS OWNER AS
INSERT INTO my_db.dbo.report_table
(
column_a
)
SELECT
column_b
FROM data_mart.dbo.source_table
WHERE
foo = 'bar';
These run fine when I execute the query in SQL Server Management Studio. When I try to execute them using EXEC load_stuff, the procedure fails with a security warning:
The server principal "the_user" is not able to access the database "data_mart" under the current security context.
The OWNER of the sproc is dbo, which is the_user (for the sake of our example). The OWNER of both databases is also the_user and the_user is mapped to dbo (which is what SQL Server should do).
Why would I be seeing this error in SQL Server? Is this because the user in question is being aliased as dbo and I should use a different user account for my cross-database data access?
Edit
I understand that this is because SQL Server disables cross database ownership chaining by default, which is good. However, I'm not sure of the best practice in this situation. If anyone has any input on the best practice for this scenario, it would be greatly appreciated.
Edit 2
The eventual solution was to set TRUSTWORTHY ON on both of the databases. This allows for limited ownership chaining between the two databases without resorting to full database ownership chaining.
Why not remove EXECUTE AS OWNER?
Usually, my user executing the SP would have appropriate rights in both databases, and I don't have to do that at all.
There is no need to create login, you can just enable guest user in target DB.
grant connect to guest
This allows executing user to enter DB under guest context, and when "db chaining is ON access will not be checked in target DB.
Actually, DBO is a role (you can consider it as a group of users), not a user in himself. (Unless you can connect to SQL SERVER using dbo:passwordfordbo it's not a user).
Usually, in the wonderful world of SQL Server, if you grant userX right to execute storedprocY then X gets the right to perform all the task Y contains even if he doesn't have all the permission on all the objects used in Y.
That's an extremely useful feature to encapsulate business logic in a stored procedure. (Your user have NO access on the table but they do can EXECUTE one stored proc).
When we talk about "ownership chaining" it means the following (please correct me if I am wrong though)
- If ownership chaining is disabled: the right to execute procedureX will work as long as all the required objects are in the same database
- Of chaining is enabled: That "privilege" will expands towards all databases.
Hope that helps,