SQL Server OPENROWSET without SYSADMIN role - sql-server

We extensively use the OPENROWSET function to import .CSV and Excel files into our SQL Server 2012 environment, using MSDASQL or ACE:
SELECT *
FROM OPENROWSET ('MSDASQL',
'DRIVER={MICROSOFT access TEXT DRIVER (*.TXT, *.CSV)};',
'SELECT * FROM E:\INCOMING\REPORT_EXTRACT.CSV')
Or using ACE:
SELECT * FROM OPENROWSET('MICROSOFT.ACE.OLEDB.12.0','TEXT;DATABASE=E:\INCOMING\;HDR=YES;', 'SELECT * FROM [REPORT_EXTRACT.CSV]');
We're experiencing the classic error message:
Msg 7415, Level 16, State 1, Line 1
Ad hoc access to OLE DB provider 'MSDASQL' has been denied. You must access this provider through a linked server.
The ONLY workaround to enable this, is granting said user(s) with the SYSADMIN role - obviously not ideal.
The location of the file(s) is on the server itself, for which the users accessing DO have the necessary permissions to access that file folder. The SQL Server service is running under the local system account with permission to interact with the desktop.
We've tried the following workarounds/fixes to no avail:
1 Executed the following code:
EXEC master . dbo. sp_MSset_oledb_prop N’Microsoft.ACE.OLEDB.12.0′ , N’AllowInProcess’ , 1
GO
EXEC master . dbo. sp_MSset_oledb_prop N’Microsoft.ACE.OLEDB.12.0′ , N’DynamicParameters’ , 1
GO
*2 The DisAllowAdHocAccess registry fix:
This is the current state:
3 Adding the ADMINISTER BULK OPERATIONS permission to the said users
We have dozens of expressions and files within our procedures that use OPENROWSET, therefore BULK INSERT, building SSIS packages, leverage Excel files as linked servers are NOT feasible options.
Any suggestions?

Wow - After YEARS of troubleshooting, I finally figured out what it was!
The registry entry value that controls the Allowing of Ad-hoc access, relies on the DisallowAdHocAccess being in that EXACT sentence case.
In our case, the "A" in AdHoc was not capitalized:
To fix this, I:
Deleted the registry value as described
Re-enabled the Disallow AdHoc Access option (Which re-created the registry value)
Manually set the Registry DisallowAdHocAccess value to "0"
Problem solved!

Related

Unable to run SQL Server stored procedure query in SSMS after adding credential parameter

I am new to using using stored procedure and Azure storage account. I am exploring the following guide at:
https://www.sqlshack.com/how-to-connect-and-perform-a-sql-server-database-restore-from-azure-blob-storage/
and have created a credential in my database 'Security' > 'Credential' folder in SSMS.
Query that I ran in SSMS:
--using the url and the key
CREATE CREDENTIAL [Credential_BLOB]
WITH IDENTITY= 'https://<account>.blob.core.windows.net/',
SECRET = '<storage account key -> which I enter my Access Key 1>';
Result:
After which I proceed to run the following stored procedure where I want to restore the backup from BLOB storage:
RESTORE DATABASE Database_Name FROM URL = 'https://<account>.blob.core.windows.net/Container/SampleDatabase.bak'
WITH CREDENTIAL = 'Credential_BLOB',
And I get this error:
Msg 41901, Level 16, State 2, Line 3
One or more of the options (credential) are not supported for this statement in SQL Database Managed Instance. Review the documentation for supported options.
However, from the guide which I input the link above, they were able to run the query:
I tried to google for the syntax of the RESTORE statement from the Microsoft Docs library and others who may have encountered similar issue but I did not find any effective result. I would appreciate your help if you have encountered something similar and would like to share your solution. Thank you!
From the error which you have shared, it is easy to interpret that you are using the SQL Database Managed Instance. But the link you have shared doesn't mention anywhere which SQL Server it is using. The approach mentioned in that link might not work in your case because of difference in SQL servers and statement compatibility.
Then, I tried the steps which are given in the Microsoft official document (link shared by #Nick.McDermaid in the comment section). It is working fine without any issue.
Please follow the steps below to achieve the requirement (applicable for SQL Server 2016 (13.x) and later, Azure SQL Managed Instance only).
Use the GUI in SQL Server Management Studio to create the credential by following the steps below.
Connect with your SQL Server 2016 (13.x) and later or Azure SQL Managed Instance
Right-click your database name, hover over Tasks and then select Back up to launch the Back Up Database wizard.
Select URL from the Back up to destination drop-down, and then select Add to launch the Select Backup Destination dialog box.
Select New container on the Select Backup Destination dialog box to launch the Connect to a Microsoft Subscription window.
Sign in to the Azure portal by selecting Sign In and then proceed through the sign-in process. Select your subscription from the drop-drown.
Select your storage account from the drop-down. Select the container you created already from the drop-down. Select Create Credential to generate your Shared Access Signature (SAS). Save this value as you'll need it for the restore.
I also tried to restore the database using the newly created credential and it is working fine.
To create the credential using T-SQL, please follow the steps provided in this link.

Integration Services Catalog folder permissions changed

Question: Do any of the SQL Server systems tables in either SSISDB or MSDB contain information that would allow me to discover which users are making changes to folder permissions in the Integration Services Catalog?
Background: I saw that a SQL Agent Job was failing with the following error description:
Cannot access the package or the package does not exist. Verify that
the package exists and that the user has permissions to it.
Upon researching the issue, I found that the service account's permissions to the folder that contains the relevant packages has been removed. I would like to perform a diagnostic to see who removed the permissions and when.
Additionally, configuration management by our IT Operations Group has been a challenge as the SQL Servers have not been kept in-line across environments (i.e., development, test, stage, and production) with respect to at least the following:
Patch Management
Memory Management
Permissions Management
Research: I have checked the Sysssispackages table in MSDB but that does not appear helpful and the tables in SSISDB all appear to be integer based. My background is in database development and less so in database management. Any help is appreciated.
The changes to permissions are not audited for the SSISDB.
When you're using the UI to grant/deny permissions for a folder/project, that is translated to a call to catalog.grant_permission/catalog.deny_permissions Those check whether you're in an admin role (server or database) and if so, then call the internal.update_permission with a value of 0/1 for grant vs deny.
I tested this versus 2014 but I would be surprised if it's any different in 2016/2017/2019
SQL Server itself keep track of permission changes via the system trace. Assuming the change was recent, you can try a query like this
SELECT
f.ObjectName
, f.NTUserName
, f.StartTime AS ChangeStartTime
, f.EventClass
, t.start_time AS TraceStartTime
, t.last_event_time AS TraceLastEventTime
, t.event_count
, f.DatabaseID
, f.TransactionID
--, f.NTDomainName
, f.HostName
, f.ClientProcessID
--, f.ApplicationName
, f.LoginName
, f.SPID
, f.EventSubClass
, f.ObjectID
, f.ObjectType
, f.DatabaseName
FROM
sys.traces t
CROSS APPLY sys.fn_trace_gettable(REVERSE(SUBSTRING(REVERSE(t.path), CHARINDEX('\', REVERSE(t.path)), 260)) + N'log.trc', DEFAULT) f
WHERE
t.is_default = 1
AND f.EventClass IN
(102, 103, 104, 105, 106, 108, 109, 110, 111)
AND f.DatabaseName = 'SSISDB';
Event class breakout is at
https://www.databasejournal.com/features/mssql/a-few-cool-things-you-can-identify-using-the-default-trace.html
I don't think that SSISDB either MSDB contains informations about permissions changes auditing. If think this should be done on the SQL Server database engine. You should have an auditing process that monitor all changes on the SQL Server Instance.
You can refer to the following links to read more on how you can track or audit permissions changes:
Tracking SQL Server Database Permission Changes
SQL Server Audit
Audit SQL Server permission changes to improve overall security
To check out what are the tables and informations stored inside MSDB and SSISDB check the following links:
SSIS Catalog
List of tables in SSISDB
The system msdb database, introduction and tips
msdb Database

Unable to call stored procedure from linked server

I am facing a strange issue. I have a linked server on ServerB for ServerA
Now, when I am calling a stored procedure from ServerB like
EXEC [ServerA].[Db].[dbo].[SpName] #Param1 #param2
I am getting error that
The EXECUTE permission was denied on the object 'SpName', database 'Db', schema 'dbo'.
But now when I am executing below query it is returning me result:
SELECT *
FROM [ServerA].[Db].[dbo].[tblName]
I don't know that why I am not able to execute stored procedure from ServerB. I am Db_Owner on both the server.
Screenshot of Linked server security
Linked server catalog
If a linked server query fails, the things to check are (in rough order of probability):
Try logging in locally on the linked server to test access directly. If you have no local access, obviously you won't have it through the link either.
Verify the correct credentials as used when accessing the linked server, and not another user you're not expecting. You can check this with EXEC ('SELECT USER_NAME(), SUSER_NAME()') AT [Server]; if the user name is not what you're expecting, check your linked server definition for the correct login mappings. If you can't access the server at all (any query fails), you have other problems (like Kerberos authentication issues if you're using integrated authentication).
Perform a sanity check that you're accessing the correct server with EXEC ('SELECT ##SERVERNAME') AT [Server]. The network name of a linked server can be changed using sp_setnetname, so the name you use to a access the server isn't necessarily the machine name.
If all else fails, dropping and recreating the linked server definition is always an option, but obviously this could disrupt production work.

Creating a linked server from SQL Server X64 to text and Excel using the Access driver

We are now in progress of moving all our production databases from a SQL Server 2005 32 bit instance to a brand new SQL Server 2012 64 bit instance.
one of the main hardships that our developers still suffer is Linked Servers.
We have a lot of programs that need to get some data from text, csv or excel files, and the way it's implemented is with a linked server to text files so you can easily throw a select statement to the text file and insert it into a table.
The problem raised that the 32 bit server used the Microsoft.Jet.OLEDB.4.0 driver the files where on a sheared directory that had full permissions for everyone and we never ran into security issues.
On the new 64 bit server we added a linked server with the following syntax:
USE [master]
GO
EXEC master.dbo.sp_addlinkedserver
#server = N'TEMP_FILES_1'
, #srvproduct=N''
, #provider=N'Microsoft.ACE.OLEDB.12.0'
, #datasrc=N'\\SERVER-APP01\BWA\TempFiles'
, #provstr=N'Text'
Note:
The data source is on a network share.
The MSSQL service runs as the domain administrator account.
I'm logged in remotely as the domain administrator which is of course a local administrator too.
The \\SERVER-APP01\BWA\TempFiles directory has full access set for everyone.
Now when i run EXEC sp_testlinkedserver [TEMP_FILES_1] i get the following error message:
OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "TEMP_FILES_1" returned message "'\\SERVER-APP01\BWA\TempFiles' is not a valid path. Make sure that the path name is spelled correctly and that you are connected to the server on which the file resides.".
This is definitely a security issue, but the funny part is that when i run xp_cmdshell 'dir \\SERVER-APP01\BWA\TempFiles' it returns records so obviously the service has access to this folder...
On the other side on my local computer i also have a 64 bit instance with the same linked server and it works like a charm!
I've been crawling around the internet to find a solution to my problem but seems that linked servers to text files is used very little especially with 64 bit.
We had to copy the file to a drive on the destination SQL Server system before we could read the data as below:
EXEC xp_cmdshell 'net use y: \\[source directory path] [pw] /USER:[active user]'
EXEC xp_cmdshell 'copy y:\[source file] [destination directory]'
EXEC xp_cmdshell 'net use y: /delete'

Unable to access CSV file using linked server using any login other than 'sa' [duplicate]

This question already has an answer here:
SQL Server Linked Server to Microsoft Access
(1 answer)
Closed 2 years ago.
I've set up a linked server to read a set of CSV files located locally on the SQL Server machine, as follows:
USE master
go
IF EXISTS (SELECT * FROM sys.servers WHERE name = 'MyLink')
EXEC sp_dropserver 'MyLink', 'droplogins';
EXEC sp_AddLinkedServer #server = 'MyLink',
#srvproduct = '',
#provider = 'Microsoft.ACE.OLEDB.12.0',
#datasrc = 'C:\Data\Feeds',
#provstr = 'Text'
EXEC sp_AddLinkedSrvLogin MyLink, FALSE
go
The following code then works perfectly, provided I'm logged in as 'sa' (either syntax works):
SELECT * FROM MyLink...myFile#csv
SELECT * FROM OPENQUERY(MyLink,'select * from myFile.csv')
If I log in as any other user, however, I get the following error:
Msg 7416, Level 16, State 2, Line 1
Access to the remote server is denied because no login-mapping exists.
Trying to change the remote login, either via script, or by modifying the linked server properties in SSMS to add a mapping, not only doesn't work but also breaks the ability of 'sa' to run the select statements.
BTW, I'm trying to work around a known bug in SSIS where it cannot handle CSV with commas inside double-quote-delimited fields. I stumbled across this post which describes using a linked server to get around the problem without having to code a custom parsing routine. Works great, except for the whole security thing; I don't want my application connecting as 'sa'. I'm using SQL 2005 SP3.
Any ideas on getting this to work with a run-of-the-mill login?
TIA,
Jim
#JustinStolle When I set it up as you describe, I get a different error for the non-sa user (sa still seems to work):
OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "MyLink" returned message "Cannot start your application. The workgroup information file is missing or opened exclusively by another user.".
Msg 7399, Level 16, State 1, Line 1
The OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "MyLink" reported an error. Authentication failed.
Msg 7303, Level 16, State 1, Line 1
Cannot initialize the data source object of OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "MyLink".
I can't import the file; SSIS can't handle it.
Just from doing a little testing, it seems only users in the sysadmin role can query this type of linked server since it needs permissions to work with the file system. There is probably a more thorough explanation elsewhere of which exact permissions are needed.
It seems to work when, within the linked server's security settings, I map a user with no special permissions to the local sa user or another sysadmin user (despite it being labeled "Remote User").
For a long-term solution, why not create a job that imports the CSV file to a local table? It would make maintaining permissions simpler and you'd have a defined table structure against which to write queries.

Resources