I am trying to create an UNSAFE assembly in SQL Server without having to alter any global database or server permissions such as EXEC sp_configure 'clr strict security', 0
or ALTER DATABASE MyDatabase SET TRUSTWORTHY ON
(because I'm not allowed to do either of those things on our production server). Therefore I am trying to create an asymmetric key that has a corresponding login with UNSAFE ASSEMBLY
permission as instructed by SSMS.
I run the command
use MyDatabase
CREATE ASYMMETRIC KEY MyUtilsKey
FROM EXECUTABLE FILE = 'C:\Users\Me\MyCode\MyUtils.dll';
and I receive the error
--The certificate, asymmetric key, or private key file is not valid or does not exist; or you do not have permissions for it.
I am the owner of MyDatabase
and I have verfied that the path to the file is correct. I have also verified that MyUtils.dll is signed and has a valid key pair from the command-line as follows:
sn -v MyUtils.dll # Assembly 'MyUtils.dll' is valid
sn -p MyUtils.snk publicKey.snk # Public key written to publicKey.snk
sn -tp publicKey.snk # Public key (hash algorithm: sha1): [hex key], Public key token is [hex token]
I don't know what else to try.
EDIT: I am using SQL Server 16.0.1105.1.
siggemannen was essentially right in his comment. When creating an asymmetric key from a DLL, the DLL must not reside in a subdirectory of C:\Users
, even if you are running a local instance of SQL Server.
So the correct sequence of steps (if you don't mind creating a key from an external DLL file) is as follows (with a nod of gratitude to Solomon Rutzky for his comprehensive answer and many other blog posts on the subject):
C:\Temp
).EXEC sp_configure 'clr enabled', 1;
.master
database with USE master
.CREATE ASYMMETRIC KEY MyUtilsKey FROM EXECUTABLE FILE = 'C:\Temp\MyUtils.dll';
That gets you as far as creating the asymmetric key (provided you have the necessary privileges to run these commands). To go on and create the assembly from it requires these extra steps:
master
) Create a new SQL Server principal from the asymmetric key with CREATE LOGIN MyUtilsKeyLogin FROM ASYMMETRIC KEY MyUtilsKey
.UNSAFE ASSEMBLY
with GRANT UNSAFE ASSEMBLY TO MyUtilsKeyLogin;
.USE MyDatabase
.CREATE ASSEMBLY MyUtils FROM 'C:\Temp\MyUtils.dll' WITH PERMISSION_SET = [UN]SAFE;
Two further points to note:
CREATE ASSEMBLY MyUtils FROM 'C:\Users\Me\MyCode\MyUtils.dll' ...
actually works! SQL Server can actually create assemblies from DLLs in subdirectories of C:\Users
. (I have proven this many times in testing.) It just can't create asymmetric keys from DLLs in those directories. I have no idea why, and it threw me off the scent for days.GRANT UNSAFE ASSEMBLY TO MyUtilsKeyLogin;
is still required even if all your assemblies are SAFE
! Microsoft changed the default behaviour in SQL Server 2017 and Solomon Rutzky has written extensively on this topic (e.g., https://sqlquantumleap.com/2017/08/07/sqlclr-vs-sql-server-2017-part-1-clr-strict-security/). I can highly recommend his comprehensive tutorial on the SQL CLR at https://www.sqlservercentral.com/steps/stairway-to-sqlclr-level-1-what-is-sqlclr.