Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Data Management

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « SQL Server Developer Tips and TricksI'm a Radio Star! I'm Talking SSRS on RunAs Radio »
    comments

    It’s very common to come across user-defined modules that are written to execute as the owner.  Not to be confused with the EXECUTE AS, the EXECUTE AS Clause will change the account context that is used to validate if the procedure, function etc… can be executed under the credentials.  This can be useful when you want to control permissions to a certain extent.  However, it can also be problematic when certain ownership changes have been made.

    Troubleshooting Failures

    One of the most common failures that you will run into when the EXECUTE AS OWNER is used, is a failure to execute the module with access denied error messages.  Now, at first this can be confusing but the error does point to the area that is the culprit.  This error can even be shown when a user is in the sysadmnin server role and has complete control of the machine.  For example, a SQL Express installation may be used for mobile applications and later synchronized back to a repository.  Even with the sysadmin server role membership, a call to say, a procedure using the EXECUTE AS OWNER, can fail based on the ownership hierarchy that is in place.

    Database Ownership

    First, review the ownership of a database.  If a database is created under sa ownership, the ownership flows to all the objects under it unless specifically changed.  This would allow the EXECUTE AS OWNER to be used freely and execute everything that falls in the confines of the database ownership and sa context.  If the owner is change, possibly during a restore or some other reasoning, the objects that fall under it will fail with the EXECUTE AS OWNER are essentially broken.

    Let’s look at an example.  Create the following database

    1. CREATE DATABASE [OwnerTest] ON  PRIMARY
    2. ( NAME = N'OwnerTest', FILENAME = N'C:\OwnerTest.mdf' , SIZE = 409600KB , FILEGROWTH = 2%)
    3.  LOG ON
    4. ( NAME = N'OwnerTest_log', FILENAME = N'C:\OwnerTest_log.ldf' , SIZE = 52224KB , FILEGROWTH = 2%)
    5. GO
    6. ALTER DATABASE [OwnerTest] SET RECOVERY SIMPLE
    7. GO
    8. USE OwnerTest
    9. GO
    10. EXEC sp_changedbowner sa
    11. GO

    Notice we changed the owner to sa.  This was to set the database up for the example. The owner, by default, would be the account executing the statement above otherwise.

    Create a simple procedure to test

    1. CREATE PROCEDURE Get_OwnerText
    2. WITH EXECUTE AS OWNER
    3. AS
    4. SELECT SUSER_SNAME()
    5. GO
     

    Run the procedure and review the results

    This is all expected behavior.

    Create another database on a different instance but leave the owner as a user that does not have rights on the first SQL Server instance to any objects in the database itself or a valid login.

    1. CREATE DATABASE [OwnerTest2] ON  PRIMARY
    2. ( NAME = N'OwnerTest2', FILENAME = N'C:\OwnerTest2.mdf' , SIZE = 409600KB , FILEGROWTH = 2%)
    3.  LOG ON
    4. ( NAME = N'OwnerTest2_log', FILENAME = N'C:\OwnerTest2_log.ldf' , SIZE = 52224KB , FILEGROWTH = 2%)
    5. GO
    6. ALTER DATABASE [OwnerTest2] SET RECOVERY SIMPLE
    7. GO

    Run a simple backup of the database created on the second instance

    1. BACKUP DATABASE [OwnerTest2] TO  DISK = N'C:\OwnerTest2.bak' WITH NOFORMAT, NOINIT,  NAME = N'OwnerTest2-Full Database Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10
    2. GO

    Results

    58 percent processed.

    77 percent processed.

    81 percent processed.

    92 percent processed.

    Processed 216 pages for database 'OwnerTest2', file 'OwnerTest2' on file 1.

    100 percent processed.

    Processed 2 pages for database 'OwnerTest2', file 'OwnerTest2_log' on file 1.

    BACKUP DATABASE successfully processed 218 pages in 0.227 seconds (7.472 MB/sec).

     

    Use the backup from the second instance housing database OwnerTest2 and restore it, replacing OwnerTest on the first instance.

    1. USE Master
    2. GO
    3. RESTORE DATABASE [OwnerTest] FROM  DISK = N'C:\OwnerTest2.bak' WITH  FILE = 1,  
    4. MOVE N'OwnerTest2' TO N'C:\OwnerTest.mdf',  
    5. MOVE N'OwnerTest2_log' TO N'C:\OwnerTest_log.ldf',  
    6. NOUNLOAD,  REPLACE,  STATS = 10
    7. GO

    Results

    58 percent processed.

    100 percent processed.

    Processed 216 pages for database 'OwnerTest', file 'OwnerTest2' on file 1.

    Processed 2 pages for database 'OwnerTest', file 'OwnerTest2_log' on file 1.

    RESTORE DATABASE successfully processed 218 pages in 0.547 seconds (3.101 MB/sec).

     

    Make sure that a query window is open with the context as a user that is in the sysadmin server role or that is an owner of the database, OwnerTest.  This is simply to show the high level access that the account has, still will not execute the procedure successfully.  Execute the procedure that was created earlier, Get_OwnerTest.

    Msg 15517, Level 16, State 1, Procedure Get_OwnerText, Line 0

    Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.

     

    The message comes up that directs us to the user that is executing the procedure does not have rights to do so.  This is due to the database ownership mentioned before.  At this point, the owner of the database is a login that does not exist on the server nor has any access or capable means of being authenticated.  Since this occurs, the procedure fails because the account is either in an orphaned state or simply, the account context does not have access.  The more interesting aspect of this is, the owner will show as the previous over of the database.  This essentially means a normal troubleshooting step of validating the owner may tell someone that the ownership is fine.  However, it is not. You can review this by using the SP_HELPDB system procedure.

    Run the last change ownership procedure to move the ownership back to sa or another account that has full rights.

    1. EXEC sp_changedbowner sa
    2. Go

     

    Run the procedure again to validate it is successful.

    Conclusion

    Using the EXECUTE AS Clause does have value and can allow the ability for modules to be executed with limited needs put into security.  However, it isn’t as secure as creating a solid security setup and schema setup and controlling each object execution under the executing account. It is also prone to some errors when the chain of ownership has been broken.

    About the Author

    Ted Krueger is a SQL Server MVP and has been working in development and database administration for 13+ years. Specialties range from High Availability and Disaster / Recovery setup and testing methods down to custom assembly development for SQL Server Reporting Services. Ted blogs and is also one of the founders of LessThanDot.com technology community. Some of the articles focused on are Backup / Recovery, Security, SSIS and working on SQL Server and using all of the SQL Server features available to create stable and scalable database services. @onpnt Personal Blog over at http://onpnt.wordpress.com/
    Social SitingsTwitterLinkedInLTD RSS Feed
    3050 views
    InstapaperVote on HN

    No feedback yet

    Leave a comment


    Your email address will not be revealed on this site.

    To mislead the spambots.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)