patternsqlMinor
Assembly deployment with permission UNSAFE or EXTERNAL_ACCESS using asymmetric key
Viewed 0 times
asymmetricwithpermissionunsafeassemblyexternal_accessusingdeploymentkey
Problem
When we are trying to deploy an assembly with PERMISSION_SET=UNSAFE or EXTERNAL_ACCESS, we are getting following error message by SQL Server:
We are not setting database trustworthy=ON, instead we are creating asymmetric key using ALGORITHM = RSA_2048. Following is the sample code:
But this error is not getting resolved. I even provided sysadmin access to SampleClrLogin login for my database and master database, but it did not work. Can you guys please provide some insight to solve this issue.
CREATE ASSEMBLY for assembly 'System.ServiceModel.Internals' failed because
assembly 'System.ServiceModel.Internals' is not authorized for
PERMISSION_SET = UNSAFE. The assembly is authorized when either of the
following is true: the database owner (DBO) has UNSAFE ASSEMBLY permission
and the database has the TRUSTWORTHY database property on; or the assembly
is signed with a certificate or **an asymmetric key that has a
corresponding login with UNSAFE ASSEMBLY permission.**We are not setting database trustworthy=ON, instead we are creating asymmetric key using ALGORITHM = RSA_2048. Following is the sample code:
USE master;
GO
IF NOT EXISTS (SELECT 1 FROM sys.asymmetric_keys WHERE [name]='SampleClrKey')
BEGIN
CREATE ASYMMETRIC KEY [SampleClrKey] WITH ALGORITHM = RSA_2048
CREATE LOGIN [SampleClrLogin] FROM ASYMMETRIC KEY [SampleClrKey];
GRANT UNSAFE ASSEMBLY TO [SampleClrLogin];
END
GOBut this error is not getting resolved. I even provided sysadmin access to SampleClrLogin login for my database and master database, but it did not work. Can you guys please provide some insight to solve this issue.
Solution
The problem is that you are creating a random new Asymmetric Key in SQL Server, which does nothing to associate the Login to the Assembly, which is what the Asymmetric Key (or Certificate) is used for.
You need to first sign the Assembly prior to loading it into SQL Server. Whether it is signed with a strong name key (which equates to an Asymmetric Key within SQL Server) or a Certificate, you then create that same Asymmetric Key or Certificate (only the public key is required) in
For examples on how to accomplish this (and in a way that can be automated via Visual Studio / SSDT), please see the series I am writing on working with SQLCLR (on SQL Server Central): Stairway to SQLCLR (Levels 7 and 8 in particular).
If you are working with SQL Server 2017 or newer, then there is an additional complication to account for which is not part of the method described in the SQL Server central articles. For that, please see the two options for the revised approach in my posts:
P.S. Thank you for spending the extra few minutes to not enable TRUSTWORTHY :-)
CLARIFICATION
Since you are trying to load an unsupported .NET Framework library, you won't be compiling that yourself so the steps I outlined above will not work here (though they are still relevant for someone simply misunderstanding and trying to create the Asymmetric Key initially within SQL Server as shown in the question).
But, given that:
then you can accomplish this (while keeping
And then:
Just keep in mind that this technique does not work with
But in general, David Browne is correct in that you should probably be using
You need to first sign the Assembly prior to loading it into SQL Server. Whether it is signed with a strong name key (which equates to an Asymmetric Key within SQL Server) or a Certificate, you then create that same Asymmetric Key or Certificate (only the public key is required) in
master and then create the signature-based Login from that.For examples on how to accomplish this (and in a way that can be automated via Visual Studio / SSDT), please see the series I am writing on working with SQLCLR (on SQL Server Central): Stairway to SQLCLR (Levels 7 and 8 in particular).
If you are working with SQL Server 2017 or newer, then there is an additional complication to account for which is not part of the method described in the SQL Server central articles. For that, please see the two options for the revised approach in my posts:
- SQLCLR vs. SQL Server 2017, Part 2: "CLR strict security" - Solution 1
- SQLCLR vs. SQL Server 2017, Part 3: "CLR strict security" - Solution 2
P.S. Thank you for spending the extra few minutes to not enable TRUSTWORTHY :-)
CLARIFICATION
Since you are trying to load an unsupported .NET Framework library, you won't be compiling that yourself so the steps I outlined above will not work here (though they are still relevant for someone simply misunderstanding and trying to create the Asymmetric Key initially within SQL Server as shown in the question).
But, given that:
- You are attempting to load
System.ServiceModel.Internalsand notSystem.ServiceModel, and
- You are not getting the error about a particular library being "malformed or not a pure .NET assembly"
then you can accomplish this (while keeping
TRUSTWORTHY OFF!) by doing the following:USE [master];
CREATE CERTIFICATE [UnsupportedFrameworkLibraryPermissions]
FROM EXECUTABLE FILE =
'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.ServiceModel.Internals.dll';
CREATE LOGIN [UnsupportedFrameworkLibraryPermissions]
FROM CERTIFICATE [UnsupportedFrameworkLibraryPermissions];
GRANT UNSAFE ASSEMBLY TO [UnsupportedFrameworkLibraryPermissions];And then:
USE [{your_DB_name_here}];
CREATE ASSEMBLY [System.ServiceModel.Internals]
FROM 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.ServiceModel.Internals.dll'
WITH PERMISSION_SET = UNSAFE;Just keep in mind that this technique does not work with
System.ServiceModel.dll. That library went from being pure MSIL pre-.NET 4.0 to mixed in .NET 4.0, and only pure MSIL libraries can be loaded into SQL Server. Using ServiceModel worked in SQL Server 2005, 2008, and 2008 R2 because those versions use CLR 2.0 which is tied to .NET Framework versions 2.0, 3.0, and 3.5 in which ServiceModel was pure-MSIL.But in general, David Browne is correct in that you should probably be using
HttpWebRequest instead (depending on what you need System.ServiceModel.Internals for).Code Snippets
USE [master];
CREATE CERTIFICATE [UnsupportedFrameworkLibraryPermissions]
FROM EXECUTABLE FILE =
'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.ServiceModel.Internals.dll';
CREATE LOGIN [UnsupportedFrameworkLibraryPermissions]
FROM CERTIFICATE [UnsupportedFrameworkLibraryPermissions];
GRANT UNSAFE ASSEMBLY TO [UnsupportedFrameworkLibraryPermissions];USE [{your_DB_name_here}];
CREATE ASSEMBLY [System.ServiceModel.Internals]
FROM 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.ServiceModel.Internals.dll'
WITH PERMISSION_SET = UNSAFE;Context
StackExchange Database Administrators Q#223976, answer score: 3
Revisions (0)
No revisions yet.