How to grant the database owner (DBO) the EXTERNAL ACCESS ASSEMBLY permission?
Asked Answered
S

7

41

When I try to create assembly in SQL 2008 from .Net assembly (.Net 3.5) I am getting the below error, error says that I have to set either of the below properties as true, how can I do that?

The database owner (DBO) has EXTERNAL ACCESS ASSEMBLY permission as TRUE

The database has the TRUSTWORTHY database property on

The assembly is signed with a certificate or an asymmetric key that has a corresponding login with EXTERNAL ACCESS ASSEMBLY permission.

The complete error is below,

CREATE ASSEMBLY for assembly 'SQLLogger' failed because assembly 'SQLLogger' is not authorized for PERMISSION_SET = EXTERNAL_ACCESS. The assembly is authorized when either of the following is true: the database owner (DBO) has EXTERNAL ACCESS 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 EXTERNAL ACCESS ASSEMBLY permission.

Scurf answered 26/3, 2013 at 14:11 Comment(0)
A
16

You must set these settings in the project file! When you right click on your project, click the Database Settings from the project configuration and select the miscellaneous tab. You should see something similar to what I have here: Project Settings

This is the same question as: Error Running CLR Stored Proc

Allix answered 26/3, 2013 at 18:10 Comment(7)
Also this applies only to SQL Server Database Project types, which I am assuming you are working with.Allix
USE database_name GO EXEC sp_changedbowner 'sa' ALTER DATABASE database_name SET TRUSTWORTHY ON which is also outlined here: https://mcmap.net/q/392383/-fileloadexception-msg-10314-error-running-clr-stored-procedureAllix
Which option (in the picture) are we supposed to choose?Are
@AYS and bleepzter: yes, this works, but should be avoided unless absolutely necessary. Please see my answer for more details.Iams
"Trustworthy" was the switch that made it work for me.Tug
Trustworthy is not a fix. You are effectively telling SQL Server to access anything so long as it has a strong name or certificate, which defeats the purpose of a ASYMMETRIC key in the first place.Hyperostosis
Trustworthy is bad, read @SolomonRutzky answer. Besides, if you detach DB and reattach it (or restore a backup), Trustworthy will be Off again, meaning users might be unhappy, because you forgot to set it to Yes.Seabrooke
M
45

This worked for me:

EXEC sp_changedbowner 'sa'
ALTER DATABASE [dbase] SET trustworthy ON

and I also did this:

sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO

sp_configure 'clr enabled', 1;
GO
RECONFIGURE;
GO

sp_configure 'show advanced options', 0;
GO
RECONFIGURE;
GO
Mendel answered 30/6, 2014 at 10:37 Comment(2)
@gotqn and hoggar: yes, this works, but should be avoided unless absolutely necessary. Please see my answer for more details.Iams
This helped, for some reason I actually needed to switch the owner to sa before the rest would work.Dhole
I
40

⚠ ‼ Please do not set TRUSTWORTHY ON ... ⚠

...unless absolutely necessary‼ And, it should pretty much never be "necessary", even when loading an Assembly that you did not build (you can always add another certificate, or worst-case: sign after loading into SQL Server), or when loading .NET Framework libraries that aren't "supported" and hence aren't already in SQL Server's CLR host (you can use the certificate they are signed with, or worst-case: sign after loading into SQL Server). Setting the database to TRUSTWORTHY ON opens up a security hole, and for more info on that, please see:

PLEASE, Please, please Stop Using Impersonation, TRUSTWORTHY, and Cross-DB Ownership Chaining

Instead,

it is much better to do the following:

USE [master];

CREATE ASYMMETRIC KEY [SomeKey]
  AUTHORIZATION [dbo]
  FROM EXECUTABLE FILE = 'C:\path\to\Some.dll';

CREATE LOGIN [SomeLogin]
  FROM ASYMMETRIC KEY [SomeKey];

GRANT EXTERNAL ACCESS ASSEMBLY TO [SomeLogin]; -- or "UNSAFE" instead of "EXTERNAL ACCESS"

The above only needs to be done once per Instance, per key. So if you use the same snk / pfx file for all of your assemblies, then the steps shown above only need to be done once per SQL Server Instance; the number of Assemblies and databases containing those Assemblies does not matter. Or, if signing with a Certificate, then just replace ASYMMETRIC KEY with CERTIFICATE in the example code shown above.

This approach allows you to keep better security on the database (by keeping TRUSTWORTHY set to OFF) and allows for more granular control of which assemblies are even allowed to be set to EXTERNAL_ACCESS and/or UNSAFE (since you can separate by using different keys for signing and Logins based on those different keys).

However, if you must use the TRUSTWORTHY ON method, then the database owner does not need to be sa. The requirement is merely that the Login registered as the database owner has been granted either EXTERNAL ACCESS ASSEMBLY or UNSAFE ASSEMBLY (same two permissions shown above for the Asymmetric Key-based Login). Meaning:

USE [master];
GRANT UNSAFE ASSEMBLY TO [{Login-that-is-dbo-for-DB-containing-Assembly}];

For a more detailed walk-through of the security options, please see the following article that I wrote on SQL Server Central: Stairway to SQLCLR Level 4: Security (EXTERNAL and UNSAFE Assemblies).


For a detailed walk-through of how to automate this via Visual Studio / SSDT, please see the following 3 articles (a 3-part series), also on SQL Server Central:

Also, since writing those 3 articles, I have come up with an easier method using T4 templates but have not had time to write that up yet. When I do, I will update this answer with a link to that article.

UPDATE

SQL Server 2017 introduced a new complication in the form of a server-level configuration option named "CLR strict security". It is enabled by default and requires that ALL Assemblies, even those marked as SAFE, be signed with a Certificate or Asymmetric Key, have the associated Login, and that the Login has the UNSAFE ASSEMBLY permission granted (not good enough to grant EXTERNAL ACCESS ASSEMBLY). Please see my answer to the following S.O. question for more details on this new "feature":

CLR Strict Security on SQL Server 2017

Iams answered 23/8, 2015 at 18:16 Comment(6)
How can we use signed assemblies if our project requires (reference) .NET framework assemblies ? My project needs System.Runtime.Serialization but when I try to run CREATE ASYMMETRIC KEY [SystemRuntimeSerializationKey] AUTHORIZATION [dbo] FROM EXECUTABLE FILE = 'C:\path\to\System.Runtime.Serialization.dll';, I get this error: An error occurred during the generation of the asymmetric keyNichollenicholls
@Nichollenicholls Hey, I realize that you asked this separately here ( https://mcmap.net/q/392382/-is-it-possible-to-create-an-asymmetric-key-for-a-net-framework-assembly-in-sql-server-2014 ), but to answer it here as well: I do not believe that is possible. Your custom Assemblies should be signed and using an Asymmetric Key, but I don't think there is anything you can do with unsupported .NET Framework DLLs or any 3rd Party DLL that is signed and you don't have access to the private key. I give more details in your other question that I linked to above.Iams
This really should be marked as the answer. The 'SET TRUSTWORTHY ON' solution is a quick-and-dirty or a last resort.Stenosis
is there a way to automate this process adding it to the publish script that visual studio makes?Canopus
@GonzaPiotti Yes, there is. I just updated my answer with links to articles that I had not yet written when I posted this answer that walk you through one method of doing it. As I mention in the update, I had come up with an ever better / easier method since writing those articles but haven't had time to document it yet. I am working on that and will hopefully have it done soon.Iams
If you get error 'The certificate, asymmetric key, or private key file is not valid or does not exist; or you do not have permissions for it.' then verify SQL can access it by running xp_cmdshell 'DIR "C:\path\to\"'Thermion
A
16

You must set these settings in the project file! When you right click on your project, click the Database Settings from the project configuration and select the miscellaneous tab. You should see something similar to what I have here: Project Settings

This is the same question as: Error Running CLR Stored Proc

Allix answered 26/3, 2013 at 18:10 Comment(7)
Also this applies only to SQL Server Database Project types, which I am assuming you are working with.Allix
USE database_name GO EXEC sp_changedbowner 'sa' ALTER DATABASE database_name SET TRUSTWORTHY ON which is also outlined here: https://mcmap.net/q/392383/-fileloadexception-msg-10314-error-running-clr-stored-procedureAllix
Which option (in the picture) are we supposed to choose?Are
@AYS and bleepzter: yes, this works, but should be avoided unless absolutely necessary. Please see my answer for more details.Iams
"Trustworthy" was the switch that made it work for me.Tug
Trustworthy is not a fix. You are effectively telling SQL Server to access anything so long as it has a strong name or certificate, which defeats the purpose of a ASYMMETRIC key in the first place.Hyperostosis
Trustworthy is bad, read @SolomonRutzky answer. Besides, if you detach DB and reattach it (or restore a backup), Trustworthy will be Off again, meaning users might be unhappy, because you forgot to set it to Yes.Seabrooke
R
6

Following code worked for me for integrated security:

ALTER DATABASE dtabasename SET TRUSTWORTHY ON;
GO

ALTER AUTHORIZATION ON DATABASE::dtabasename TO [DOMAIN\UserName]
GO
Remus answered 20/10, 2014 at 12:38 Comment(0)
S
5

This works for:

  • Visual Studio 2015 Update 2.
  • Visual Studio 2017.
  • Visual Studio 2017 and SQL Server 2019 (thanks @Ramkumar Sambandam).

In your project settings, select "External Access":

enter image description here

On publish, the error message says that it cannot accept "EXTERNAL_ACCESS" unless the assembly is set to "Trustworthy".

So, in the project settings, set the assembly to "Trustworthy":

enter image description here

This meant that I was able to run a sample user defined function that listed files on the local hard drive.

If the security is still too restrictive, add the attribute DataAccess = DataAccessKind.Read to your UDF, e.g.:

[Microsoft.SqlServer.Server.SqlFunction(FillRowMethodName = "FindFiles", DataAccess = DataAccessKind.Read, TableDefinition = "FileName nvarchar(500), FileSize bigint, CreationTime datetime")]

Update 2017-07-02

On SQL Server 2016 + Visual Studio 2015, you might also have to do the following:

  • use master;grant unsafe assembly to [Domain\Username];
  • Run any programs (such as Visual Studio or any C# utilities) in Administrator mode to give them sufficient permissions to publish UNSAFE assemblies.

If nothing works, try connecting using username sa and your administrator password. This will always work, regardless of whether Visual Studio is run in Administrator mode or not.

Update 2020-01-17

Updated list of compatible VS + SQL Server combinations.

Sibship answered 2/4, 2016 at 21:36 Comment(3)
Looks like I accidentally down-voted this and didn't realize it until now. If you make a small edit and unlock my vote--I'll change that to an up-vote.Urata
above setting changes work for sql 2017 and vs 2019Malanie
@RamkumarSambandam Thanks! I've updated the answer to reflect this.Sibship
L
3

This is how I managed to make it work:

ALTER DATABASE databasename SET trustworthy ON

sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO

sp_configure 'clr enabled', 1;
GO
RECONFIGURE;
GO

sp_configure 'show advanced options', 0;
GO
RECONFIGURE;
GO

/
DROP ASSEMBLY assemblyname

GO


CREATE ASSEMBLY assemblyname
FROM 0x4D5A9000.....
WITH PERMISSION_SET = EXTERNAL_ACCESS
Levelheaded answered 30/9, 2014 at 11:5 Comment(0)
S
2

this single line solves the problem for me

use master;
grant external access assembly to [domain\username]
Sherilyn answered 3/10, 2013 at 8:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.