Amazon RDS SQL Server Change Database Owner - sql-server

I know I can't make my user in RDS a sysadmin...but can I at least change the database owner from rdsa to my own user? If I use SSMS and go to change the Owner in the database properties, I get the message:
The proposed new database owner is already a user or aliased in the database
Why do I want to do this instead of just adding my user to the db_owner role?
I have indexed views I want to create, and when trying to do so, I get the error
Index cannot be created on view '...' because the underlying object '...' has a different owner.
I know that I can manually use ALTER AUTHORIZATION on the underlying objects to allow this, as described here: https://dba.stackexchange.com/questions/9436/sql-server-2008-cannot-create-index-on-indexed-view. But I really don't want to do that for every single object referenced by every one of my indexed views.
I'm certainly open to suggestions on alternative approaches.
Thanks.

Index cannot be created on view '...' because the underlying object
'...' has a different owner.
This is the real problem you're trying to solve, right? Changing the database owner (which would be done by running ALTER AUTHORIZATION ON DATABASE::<dbname> TO <loginname>) is just a red herring.
To solve this problem is unlikely you need change th owner of the underlying object, is far more likely you want to change the owner of the view, and probably correct solution is to create the view in the same schema as the underlying table:
create view schema.indexedView
with schemabinding
as
select ...
from schema.table
where ...
Note that I say 'likely' and 'probably', this is not excuse I'm uncertain of the solution. Is because only you can tell us who the owner should be, based on the specific business rules, audit settings and access permissions of your site. Also, the fact that everything is database contained (the table, the indexed view, the schema containing the table and the owner of the schema) it means that the fact that this is an RDS instance is completely irelevant.

Related

How to create view in Snowflake based on a query that uses multiple roles and multiple databases?

I have multiple Snowflake roles, each one gives me reading access to different data warehouses/databases. Also, I have one role that gives me write access to a Sandbox schema. Some of the latest projects I'm working on require manipulating and joining data across warehouses/databases. Selecting my role as ALL, I have managed to query the data and view the final result in a Snowflake worksheet. However, when it comes to creating a view in the Sandbox schema, I get the following error:
"SQL compilation error: Cannot create permanent objects while using role ALL. Use TEMPORARY keyword to create a temporary object instead." Any idea how to workaround this error?
This is an inherent limitation of the ALL role. You can get by (as the error instructs) by creating a table (first temporary, then permanent) instead of a view (temporary views are not available) if that's an option.
The use of USE ROLE ALL; shouldn't be pervasive in proper use of Snowflake, since it supports hierarchal roles, with multiple privileges granted into a single assumed role.
Very limited object-mapped roles were necessary in other DBMS that lacked role hierarchies (or limited their levels). I recommend revising your role creation and granting strategy to use Snowflake's access controls more effectively.

grant read access on a view but not on it's underlying tables from other databases

I want to grant read permissions for a user for a view which joins 2 tables from another database.
I don't want to:
give him permission on the database where the tables are or add him as an user there.
Make him the owner of the view/schema due to the security exploits.
I don't want to create first a table, or variations of a hack table with a truncate and a stored procedure which inserts the data on a trigger.
Can this be done somehow? Maybe there's something I missed and you guys might know.
I have read these posts but they didn't solve my problem:
Grant SELECT permission on a view, but not on underlying objects
Grant Select on a view not base table when base table is in a different database
https://msdn.microsoft.com/en-us/library/ms188676.aspx
https://dba.stackexchange.com/questions/89632/sql-server-grant-select-access-to-a-user-in-a-view-and-not-in-its-tables
Thank you
Edit:
The easiest solution I came up with, after some research, is activating the cross database ownership chainingoption on the database where I'm placing the views and granting the read permission to the users. This might be in contrast with my 2nd point of things I'm trying to avoid. Is this a good idea?
Give them a login to another database on the same server, and include only your single view, with the view pointing to your secure database. Don't give that login any access to anything but the database with the view in it, and only read access to that single view. Obviously, you'll have to fully qualify your table name (e.g., from SourceDB.dbo.SomeSecretTable).
What I ended up doing:
Create an active directory group.
Add users to the AD group.
Create a login for the AD group mapped for the source DB and target DB.
Add the user on the target DB and give him permissions only for the requested views.
(Optional) Added the group on all the databases to deny select.
Couldn't find a solution for my original question without the AD group.

Why does my SQL Server column appear to have no default value even though it acts like it does?

I have a SQL Server table that has four columns in it, one of which is a datetime column with a default value of getdate(). I have two copies of this table, one in a development database server over which I have full control, and another in a production database server in which I have few permissions.
Here is how the development table looks:
I've selected the dtInsert column. Notice that this column has a default value of getdate(). The production version I have of this table is exactly the same. When I add a row to this table, the dtInsert cell defaults to getdate() like I'd expect. When a database administrator generates a script of the production table, it includes the default value constraint. However, when I view the table design in SQL Server Management Studio 2012, it shows the column as not having a default value. See here:
When I generate a database diagram, it also shows the dtInsert column as having no default value. Again, I know from testing that the dtinsert column in my production database server indeed defaults to getdate().
Is this a bug in SQL Server Management Studio version 2012? Is there some permission I don't have which brings about this behavior? Is it something else? Why does the column appear to have no default value even though it does?
Is this a bug in SQL Server Management Studio version 2012?
No.
Is there some permission I don't have which brings about this behavior?
Yes.
In a comment on the question I suggested running the following:
SELECT *
FROM sys.default_constraints
WHERE [parent_object_id] = OBJECT_ID(N'_table_name_');
The result was a row return in Production in which the [definition] column was NULL. This means that the DEFAULT CONSTRAINT is there but you either:
lack explicit and implied permissions to see the definition
have been explicitly denied the permission to see it.
You can read up on this on the MSDN page for Metadata Visibility Configuration.
Now, there are various permissions (VIEW DEFINITION, VIEW ANY DEFINITION, etc.) that affect this setting. These can be applied at various levels:
the object itself
the schema
the database
etc
Permissions get further complicated when taking into account membership in multiple Windows Groups (if those are being used).
The permission can even be granted at multiple levels. Permissions are also additive: a GRANT in 1 out of 3 Windows Groups that your Login is a member of is enough to work. However, a DENY in any of those levels takes precedence and in that case, no definition for you.
As I mentioned in a comment on the question, this is really a matter for the Production DBA(s) who configured permissions such that you can't see the definition. Without know exactly why you can't see the definition (lacking of a GRANT or presence of a DENY?) it is useless issuing GRANT statements trying to get this permissions (especially since not being able to see the definition implies that you likewise would not be able to GRANT such permission to anyone). Please go talk to whoever is in charge of Production telling them that you can't see the definition of a default constraint, but you would like to be able to. If there is a specific reason why you currently cannot, you will be told. If it is an oversight, they should correct it in a controlled fashion that might need to be replicated to other environments, etc.
It appears the difference in viewing the object in SSMS between dev and prod is due to permission differences on your user account between dev and prod.
In order to view default values on a table object you need to have at least one of the following permissions on the object to see the default value:
ALTER on OBJECT Or CONTROL on OBJECT Or TAKE OWNERSHIP on OBJECT Or
VIEW DEFINITION on OBJECT
Found this https://dba.stackexchange.com/questions/78769/minimum-sql-server-rights-that-allow-viewing-column-default-values
which seems to be pretty much answer your question :)

SQL Server Security Option w/ Intermediate Check Option? What does that mean?

This afternoon I was reviewing the security for a user in my SQL Server, in SQL Server Management Studio. I opened the Database User's Properties dialog, and went to the Securables section.
As I was cycling through the tables and stored procedures that this particular user had access to, I noticed that one of the data tables had the the Update option checked in an intermediate state. What does that mean? You can either update a row, or you can't. There is no in-between. I've included an image for reference. I would just fully check this option and save it but I'd rather not screw with the DB if this serves a worthwhile purpose.
I believe that means that that permission has been inherited and wasn't explicitly set for that user.
The GRANT statement can assign
permissions to a group or role that
can be inherited by database users.
http://msdn.microsoft.com/en-us/library/bb669084.aspx
I'm trying to find something that specifically spells out that's what the checkbox looks like in the above situation.

Determing if stored procedure can execute based on AD login

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.

Resources