Cross Database Ownership Chaining fails: not able to access the database - sql-server

I have:
A single Microsoft SQL Server 2008 R2
Two databases with some tables: DB1 and DB2 (both with the same owner)
A view in DB1, DB1.dbo.View1, that SELECT * FROM DB2.dbo.Table1
A role, ViewRole, in DB1 granted SELECT permit to the view (no other permissions)
A Windows user, DOMAIN\user, with server role set to public, who belongs to DB1's ViewRole
When the user tries to SELECT from the view, I get the error:
The server principal "DOMAIN\user" is not able to access the database "DB2" under the current security context
I have tried (and hopefully succeeded) to activate Cross Database Ownership Chaining using both:
EXEC sp_configure 'Cross DB Ownership Chaining', '1';RECONFIGURE
and
EXEC sp_dboption DB1, 'db chaining', 'true'
EXEC sp_dboption DB2, 'db chaining', 'true'
To confirm that the setting is made, I run:
SELECT name, owner_sid, is_db_chaining_on FROM sys.databases
and the result is:
name owner_sid is_db_chaining_on
DB1 0x0105...DCB510000 1
DB2 0x0105...DCB510000 1
So, why won't the user be able to SELECT from the view? There will be no error if the view only selects from a table within DB1.
Anyone has any suggestion as to what I might have missed or misunderstood?

The windows user has to have access to both databases to be able to use cross database ownership chaining.
You should also disable the option on server level for security and only enable the option in the databases.
You can read more about it here

Related

Google Cloud SQL - Unable to change DB owner on restored database from .BAK file

I have restored a SQL Server 2019 database from a .BAK file to a Google Cloud SQL instance.
I can connect to the instance using Visual Studio SQL Connection. I issue the following command to check the database owner, which should be: mydb_adm
USE master;
SELECT suser_sname(owner_sid) AS 'DB Owner' FROM sys.databases WHERE name = 'mydb';
DB Owner
--------
sqlserver
The above is expected, as the restore was done while using the sqlserver account which is the default user created when the SQL instance is provisioned by Google Cloud (according to the docs).
So, I need to change the DB owner; I execute the following command:
USE mydb
EXEC sp_changedbowner 'mydb_adm'
The system displays the following error message:
Msg 15151, Level 16, State 1, Line 1
Cannot find the principal 'mydb_adm', because it does not exist or you do not have permission.
The same message is displayed for:
ALTER AUTHORIZATION ON DATABASE::mydb TO mydb_adm;
However, the "mydb_adm" principal DOES exist, i.e.:
SELECT name, sid FROM sys.server_principals WHERE name = 'mydb_adm';
name sid
---- ---
mydb_adm 0xD81398C7DB0D724BB2738A2EC59BB554
.. so it must be a permission problem with the sqlserver account. When I query the DB, it appears the "sqlserver" user does NOT have ALTER permissions, i.e.:
UserName Permission Type Permission State
-------- --------------- ----------------
sqlserver ALTER DENY
... So how can I change the database owner or issue any ALTER commands using the "sqlserver" account? (There seems to be no way to grant the ALTER permission to the sqlserver user).
Any help / advice would be appreciated.
Thank-you to #DanGuzman for providing a "work-around", i.e.: while connected to the SQL instance using the "sqlserver" user, the following commands were used:
USE mydb;
CREATE USER mydb_adm;
ALTER ROLE db_owner ADD member mydb_adm;
After some additional digging, I also found the following in the Google Cloud docs at https://cloud.google.com/sql/docs/sqlserver/users, which states:
Cloud SQL for SQL Server is a managed service, so it restricts access
to certain system stored procedures and tables that require advanced
privileges. In Cloud SQL, you cannot create or have access to users
with superuser permissions.
Note: The sysadmin role is not supported. Therefore, you cannot run
system stored procedures that require the sysadmin role. As one of
the many examples, you cannot run the sp_OADestroy stored procedure
because it requires the sysadmin role.
As well as the following from the SQL Server docs at https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-authorization-transact-sql?view=sql-server-ver15#remarks, which state:
Requirements for the person executing the ALTER AUTHORIZATION
statement: If you are not a member of the sysadmin fixed server role,
you must have at least TAKE OWNERSHIP permission on the database, and
must have IMPERSONATE permission on the new owner login.
hence, commands such as EXEC sp_changedbowner ... or ALTER AUTHORIZATION ON DATABASE:: ... will raise the error (Msg 15151, ... you do not have permission.)
Hope that helps anyone else that may run into this type of issue.

Get number of current connections to a specific database using an SQL Server account with db_datareader database role

I have an account with db_datareader database role set on my database test_db.
Using SSMS I log in using this account (with SQL Server Authentication) and I open a new query window in order to get the number of current connections to test_db database by performing below query:
select * FROM sys.databases sd LEFT JOIN sys.sysprocesses sp ON sd.database_id = sp.dbid
WHERE database_id = 6 AND LOGINAME IS NOT NULL
where database_id = 6 corresponds to test_db.
This query returns one single row instead of many rows.
However, from SSMS If I log in using another account (with Windows Authentication) that does not have db_datareader set, If I open a new query window from SSMS and type the same query above indicated I get all the current connections to test_db database (more than one row).
Why? I need to obtain all the current connections to test_db database, not only the single connection which current user is logged in (the read only account with db_datareader database role set)
Since the SQL user you wish to return the information won't have the appropriate permissions, you will need to create a stored procedure and use EXECUTE AS
CREATE PROCEDURE dbo.GetConnectedUsers
WITH EXECUTE AS 'sa'
AS
SELECT *
FROM sys.databases sd
LEFT JOIN sys.sysprocesses sp ON sd.database_id = sp.dbid
WHERE database_id = 6 AND LOGINAME IS NOT NULL
GO
Obviously you would also need to give the limited user account you are using execute permissions to the stored procedure also
Finally I have solved by granting VIEW SERVER STATE permission to read only user as explained here.
The problem that SQL Server were not returning all the rows is because the read only user was not seeing all executing sessions on the SQL Server instance. Read only user was only seeing the current session. So setting VIEW SERVER STATE for the read only user works.

How to grant extract DDL in Sybase to specific user?

I have a Sybase database and I've created a user following this video. Now I want to grant only select and get DDL permissions to the user, I've granted select permissions on all the user tables in the database to the user using grant select on tableName to user_ro query. But I'm not able to identify which permission will allow user to get DDL of all the database objects and can only read the data. What are the least privileges or roles that are needed to be granted to the user?
Queries that I ran against the database using SQL Interactive board:
//create login under master
use master
sp_addlogin user_ro, user1234
//verify user is created successfully
select name from syslogins
//add login user to mydatabase
use mydatabase
sp_adduser user_ro
//grant select on all tables one by one
grant select on tableName to user_ro
I'm quite new to Sybase, so please correct me wherever I'm wrong.
There is no specific DDL permission in ASE.
All programs that make DDL just select from system tables the definition of a certain object. So if you have access to some database and sp_help works then you can also create DDL from an object.

SQL Server: cannot access system tables

I have an MSSQL database and a "normal" user accessing it. When I try to use tables like sys.objects, I become a permission error:
select name from sys.objects
Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object 'objects', database 'mssqlsystemresource', schema 'sys'.
Why? The documentation says
In SQL Server 2005 and later versions, the visibility of the metadata
in catalog views is limited to securables that a user either owns or
on which the user has been granted some permission.
so I think I should be allowed to use sys.objects, even if it will list only the for me visible objects...
My user have been created with
CREATE LOGIN [factoryFX20_K_user] WITH PASSWORD=N'...', DEFAULT_DATABASE=[ff20121025], DEFAULT_LANGUAGE=[English], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON
EXEC sys.sp_addsrvrolemember #loginame = N'factoryFX20_K_user', #rolename = N'serveradmin'
USE [ff20121025]
CREATE USER [factoryFX20_K_user] FOR LOGIN [factoryFX20_K_user] WITH DEFAULT_SCHEMA=[factoryFX20_K_user]
The problem was ideed the same as in The SELECT permission was denied on the object 'sysobjects', database 'mssqlsystemresource', schema 'sys': my user had some "denying" roles.
The solution was to remove this roles of the user:
USE [ff20121025]
EXEC sp_droprolemember N'db_denydatawriter', N'factoryFX20_K_user'
EXEC sp_droprolemember N'db_denydatareader', N'factoryFX20_K_user'
Thanks Jon!

security context problem when accessing through synonyms

There is a user and two databases on server (db1 and db2).
User can connect to server having default database db1 where he can exec sp.
In sp syntax we use synonyms for db2 tables under dbo scheme.
All that is done in order to allow user just connect and exec one stored procedure. It worked noraml but now The server principal "user" is not able to access the database "db2" under the current security context.
User gets output from sp when code does not touch synonyms to db2.
What should be updated? I cant grant select to user for db2 objects.
I know the question is old, but still relevant
the procedure has to have permission on the synonym object
the procedure has to have permission on the object the synonym is targeting
you have to correctly setup trustworthy database property
By default, the procedure executes under the caller account, but it can be changed with execute as clause.

Resources