I have a C# CLR (.NET 4.5) stored procedure in SQL Server 2012 that is called from within a transaction. The CLR calls a WebService that requires TLS 1.2.
Everything works fine if I use create the assembly with permission_set = UNSAFE, but I would really like to avoid this and instead use EXTERNAL_ACCESS. However, this is proving a real challenge.
There are two problems when using EXTERNAL_ACCESS:
1) I write to a log file from the CLR (for maintenance & debugging purposes), which does not work since locks are not allowed:
private static readonly object Locker = new object();
public static string LogMessage(string message)
{
message = String.Format("{0}: {1}" + Environment.NewLine, DateTime.Now, message);
lock (Locker)
{
var file = new FileStream(GetConfigValue("LogFile"), FileMode.Append, FileAccess.Write);
var sw = new StreamWriter(file);
sw.Write(message);
sw.Flush();
sw.Close();
}
return message;
}
The error message:
System.Security.HostProtectionException: Attempted to perform an operation that was forbidden by the CLR host.
The protected resources (only available with full trust) were: All the demanded resources were: Synchronization, ExternalThreading
I could log to a database table instead, but since the call to the CLR is from within a transaction, errors would cause a rollback, which would also rollback the log record. I could use the event log, but I really do not want to do this if at all possible.
2) The web service that I call requires TLS 1.2, but setting the ServerCertificateValidationCallback
is not allowed:
ServicePointManager.ServerCertificateValidationCallback = AcceptAllCertifications;
The error message:
System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
System.Security.SecurityException:
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet) at System.Security.CodeAccessPermission.Demand() at System.Net.ServicePointManager.set_ServerCertificateValidationCallback(RemoteCertificateValidationCallback value) at AcmeClr.StoredProcedures.ProcessPayment(SqlMoney amount, SqlString ticketNo, SqlString& resultCode, SqlString& resultText)
Is there anyway around this issue - is there a way to make this work without using UNSAFE?