The server principal "sa" is not able to access the database "model" under the current security context

StackOverflow https://stackoverflow.com/questions/16212179

  •  11-04-2022
  •  | 
  •  

Question

I created a stored procedure which performs a series of operations that require special permissions, e.g. create database, restore database, etc. I create this stored procedure with

execute as self

...so that it runs as SA. This is because I want to give a SQL user without any permissions the ability to run only these commands which I have defined.

But when I run this stored proc, I get

The server principal "sa" is not able to access the database "model" under the current security context.

How come SA can't access the model database? I actually ran the code in the stored proc on its own, under SA, and it ran fine.

Was it helpful?

Solution

Read Extending Database Impersonation by Using EXECUTE AS before you continue.

when impersonating a principal by using the EXECUTE AS USER statement, or within a database-scoped module by using the EXECUTE AS clause, the scope of impersonation is restricted to the database by default. This means that references to objects outside the scope of the database will return an error.

You need to use module signing. Here is an example.

OTHER TIPS

For anybody else coming here looking for this info, here is sample code that demonstrates exactly what OP (and I) wanted (based on excellent info from Remus above):

    -- how to sign a stored procedure so it can access other Databases on same server
    -- adapted from this very helpful article 
    -- http://rusanu.com/2006/03/01/signing-an-activated-procedure/

    USE [master]
    GO
    CREATE DATABASE TempDB1
    CREATE DATABASE OtherDB2
    GO
    USE TempDB1
    GO
    -- create a user for TempDB1
    CREATE USER [foo] WITHOUT LOGIN
    GO

    CREATE PROCEDURE TempDB1_SP 
    AS 
    BEGIN 
        CREATE TABLE OtherDB2.dbo.TestTable (ID int NULL)
        IF @@ERROR=0 PRINT 'Successfully created table.' 
    END
    GO

    GRANT EXECUTE ON dbo.TempDB1_SP TO [foo]
    GO

    EXECUTE AS User='foo'
        PRINT 'Try to run an SP that accesses another database:'
        EXECUTE dbo.TempDB1_SP
        GO
    REVERT

    -- Output: Msg 916, Level 14, State 1, Procedure TempDB1_SP, Line 5
    --   [Batch Start Line 14]
    -- The server principal "..." is not able to access the database 
    --    "OtherDB2" under the current security context.

    PRINT ''
    PRINT 'Fix: Try again with signed SP...'

    -- Create cert with private key to sign the SP with. 
    -- Password not important, will drop private key

    USE TempDB1
    GO
    -- create a self-signed cert
    CREATE CERTIFICATE [DB_Cert] 
        ENCRYPTION BY PASSWORD = 'Password1' 
        WITH SUBJECT = 'Signing for cross-DB SPs';
    -- Sign the procedure with the certificate’s private key
    ADD SIGNATURE TO OBJECT::[TempDB1_SP] 
        BY CERTIFICATE [DB_Cert] 
        WITH PASSWORD = 'Password1'
    -- Drop the private key. This way it cannot be used again to sign other procedures.
    ALTER CERTIFICATE [DB_Cert] REMOVE PRIVATE KEY
    -- Copy the public key part of the cert to [master] database 
    -- backup to a file and create cert from file in [master]
    BACKUP CERTIFICATE [DB_Cert] TO FILE = 'C:\Users\Public\DBCert.cer'

    USE [OtherDB2] -- or use [master] = all DBs on server accessible
    GO
    CREATE CERTIFICATE [DB_Cert] FROM FILE = 'C:\Users\Public\DBCert.cer';
    -- the 'certificate user' carries the permissions that are automatically granted 
    -- when the signed SP accesses other Databases
    CREATE USER [DB_CertUser] FROM CERTIFICATE [DB_Cert]
    GRANT CREATE TABLE TO [DB_CertUser] -- or whatever other permissions are needed
    GO

    USE TempDB1
    EXECUTE dbo.TempDB1_SP
    GO
    -- output: 'Successfully created table.'
    -- clean up: everything except the cert file, have to delete that yourself sorry
    USE [master]
    GO
    DROP DATABASE TempDB1
    DROP DATABASE OtherDB2
    GO
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top