I'm trying to get data from another database using the OPENDATASOURCE command, but I get an error about DisallowAdHocAccess.
The SQL Server version is 2008 Express Edition, running on a remote site.
OPENROWSET can be used to access remote data from OLE DB data sources
only if the DisallowAdhocAccess registry option is explicitly set to
0. When this option is not set, the default behavior does not allow ad
hoc access.
HOW TO: Use the DisallowAdHocAccess Setting to Control Access to Linked Servers
Accessing External Data
An ad hoc name is used for infrequent queries against OLE DB data
sources that are not defined as linked servers. In SQL Server, the
OPENROWSET and OPENDATASOURCE functions provide connection information
for accessing data from OLE DB data sources. By default, ad hoc
names are not supported. The DisallowAdhocAccess provider option must
be set to 0 and the Ad Hoc Distributed Queries advanced configuration
option must be enabled.
Security Note
Enabling the use of ad hoc names means that any authenticated login to
SQL Server can access the provider. SQL Server administrators should
enable this feature only for highly trusted providers that are safe to
be accessed by any local login.
OPENROWSET and OPENDATASOURCE should be used only to reference OLE DB
data sources that are accessed infrequently. For any data sources that
will be accessed more than several times, define a linked server.
Neither OPENDATASOURCE nor OPENROWSET provide all the functionality of
linked server definitions. This includes security management and the
ability to query catalog information. Every time that these functions
are called, all connection information, including passwords, must be
provided.
Related
Environment : Oracle 12C
In SQL Server, a credential is a record that contains the authentication information (credentials) required to connect to a resource outside SQL Server. This information is used internally by SQL Server. Most credentials contain a Windows user name and password.Here is Microsoft doc about Credentials in SQL Server .In SQL Server, the default is to use the service account credentials to access the resource outside SQL Server.
What is the SQL Server credential equivalent in Oracle ?
There is no direct equivalence as it depends on the resource.
For database links (which are equivalent to SQL Server linked servers), credentials are not stored as a separate object but are considered as part of the database link itself.
For local external jobs, remote external jobs, and remote database used by DBMS_SCHEDULER jobs, you need to use DBMS_CREDENTIAL.CREATE_CREDENTIAL procedure. External procedures are also using DBMS_CREDENTIAL.CREATE_CREDENTIAL.
The view DBA_CREDENTIALS can be used for DBMS_SCHEDULER jobs and external procedures but not for database links.
There may be other resources that are using credentials in a different way.
I am trying to grant a user access to export data from SQL Server into an Excel file using OPENROWSET.
The user is getting the following error:
Cannot initialize the data source object of OLE DB provider
"Microsoft.ACE.OLEDB.12.0" for linked server "(null)".
We can reproduce the issue running the following block of code, which I can run successfully and the user cannot:
INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0 Xml; HDR=YES;IMEX=0; Database=\\servername\exportdirectory\exportfile.xlsx', 'Select ExcelColumn from [TabName$]')
SELECT TOP 1 SQLColumn FROM SQLTable
The only difference I can see between the users is that those who can successfully run this command and get the data into Excel are admins on the Windows server hosting both the SQL instance and the target directory.
The user who is unable to run the code has full control permissions on the target file directory where the excel file resides and has sysadmin permissions on the SQL instance.
Is there any way to allow this user to write to this file without granting full server admin rights on the Windows server itself?
According to MS Documentation the user who is executing the command needs Administrator Bulk Operations.
This is a server level permission - bulkadmin. So you have to put any user that is going to do this in this role (at the server level) not necessarily make them a DBA.
https://learn.microsoft.com/en-us/sql/t-sql/functions/openrowset-transact-sql?view=sql-server-2017:
OPENROWSET permissions are determined by the permissions of the user name that is being passed to the OLE DB provider. To use the BULK option requires ADMINISTER BULK OPERATIONS permission.
If you cannot do that (put the user in the BulkAdmin role) you may want to use SSIS to create the spreadsheet.
You are experiencing the "double hop problem". You need to enable impersonation so that the server hosting the share will accept impersonated credentials from the SQL Server. Here is an excerpt from the security considerations section of this page: Import Bulk Data by Using BULK INSERT or OPENROWSET(BULK...) (SQL Server)
SQL Server and Microsoft Windows can be configured to enable an
instance of SQL Server to connect to another instance of SQL Server by
forwarding the credentials of an authenticated Windows user. This
arrangement is known as impersonation or delegation. Understanding how
SQL Server version handle security for user impersonation is important
when you use BULK INSERT or OPENROWSET. User impersonation allows the
data file to reside on a different computer than either the SQL Server
process or the user. For example, if a user on Computer_A has access
to a data file on Computer_B, and the delegation of credentials has
been set appropriately, the user can connect to an instance of SQL
Server that is running on Computer_C, access the data file on
Computer_B, and bulk import data from that file into a table on
Computer_C.
This page might help you get started: Kerberos Constrained Delegation Overview
I need to lock down access to a linked server object in MSSQL server.
I am building views on a host database, from which, I query to populate a staging table on my warehouse server. I am using Data Tools/SSIS to extract the view data. To simplify the SSIS package, I am using the OPENQUERYsyntax to query the linked server object that exists on my warehouse server, and connects to other SQL servers, Oracle servers, etc., through linked server objects.
To provide access to the linked servers, I have set up a local SQL login on the host db that has read access, then I use 'Be made using this security context:' and pass the local SQL login. That works just fine.
I realize now that I have a problem: any user with warehouse access can query the linked server object because of that stashed security context! I don't want that! I do need folks who should have access to be able to query (so I can write my SSIS packages), as well as the SQL Server Agent service account to have access so when the SQL Server Agent job runs as that user that it can successfully query the linked server.
I believe that the key to locking down query access to the linked server object is somewhere in the 'Local server login to remote server login mappings', but I'm having a hard time figuring that out. When I try to add for instance NT SERVICE\SQLAgent mapped to the local login with access, then save, I hit 'Login failed for 'NT AUTHORITY\ANONYMOUS LOGON' when saving.
Any ideas on how I can allow a security groups that have access, and SQL Server Agent service account to query the linked server, but not the rest of people with warehouse access?
This is known as the 'double hop' problem
(https://blogs.technet.microsoft.com/askds/2008/06/13/understanding-kerberos-double-hop/)
and to get rid of the Anonymous login error you would have to properly set up Kerberos pass-through authentication;
https://blogs.msdn.microsoft.com/farukcelik/2008/01/02/how-to-set-up-a-kerberos-authentication-scenario-with-sql-server-linked-servers/
https://www.databasejournal.com/features/mssql/article.php/3696506/Setting-Up-Delegation-for-Linked-Servers.htm
However this is quite involved - you mention that to 'simplify' the SSIS package you use a linked server, however SSIS solves exactly this problem... Why don't you just use SSIS to copy the data from the other server to avoid using a linked server?
We have some Web services (written in .NET WCF) that currently hit a Microsoft SQL Server database to retrieve/update data. We now have a requirement to also retrieve/update data from a Microsoft Access database. The Access database is currently being used by a number of legacy systems so we can't really convert it to a Microsoft SQL server database - we're stuck with an Access database.
My question is: Is there a way we can communicate with the Access database "through" Microsoft SQL Server (so that we can issue T-SQL commands to it and MS SQL Server would handle all the underlying mapping to query the Access database?) Or is it better to just communicate with the Access database via ADO.NET by exposing the location of the Access database on a network share? Does anyone have any suggestions we could try out?
Thanks all.
What about keeping the legacy access application, but moving the tables and data out of the Access application?
Access is makes a great front end to SQL server. When you build an application with Access, just like most other development tools, you have to choose what data engine and database system you going to use with Access. Access have native support built in for the JET data engine (now called ACE). Access has native support built in for SQL server. And access 2010 not only has support built in for using SharePoint, but also SQL Auzure.
So you could consider moving the data that Access now uses to SQL server, and very little if any changes need be made to the access application. So Access application function happy if the tables are in a file (mdb or accdb file), or server based like SQL server, and in fact for tables that reside on SharePoint, Access is in fact using web services to update that data on SharePoint. However, in all cases, the standard code, forms, VBA code and even the SQL used need not be changed.
So I don't the solution here is to attempt to attach SQL server to some "file" sitting in a folder but simply have Access attached to the SQL server to update the tables, and thsu no need to "transfer" data between the systems would exist anymore.
Use a linked server:
A linked server allows for access to distributed, heterogeneous queries against OLE DB data sources. After a linked server is created by using sp_addlinkedserver, distributed queries can be run against this server.
If you're only ever running on a 32-bit platform:
EXEC sp_addlinkedserver
#server = N'SEATTLE Mktg',
#provider = N'Microsoft.Jet.OLEDB.4.0',
#srvproduct = N'OLE DB Provider for Jet',
#datasrc = N'C:\MSOffice\Access\Samples\Northwind.mdb';
Or if you have to worry about 64-bit as well:
EXEC sp_addlinkedserver
#server = N'SEATTLE Mktg',
#provider = N'Microsoft.ACE.OLEDB.12.0',
#srvproduct = N'OLE DB Provider for ACE',
#datasrc = N'C:\MSOffice\Access\Samples\Northwind.accdb';
I have an Sql Server database that includes a linked server to an MS Access mdb database. The Access database has workgroup security and requires a valid user name and password. This is easily set up in the linked server dialog in sql management studio. The problem is that the Sql Server needs to be able to find the MS Access mdw file to be able to login.
The only way I have managed to get this to work is by setting the Registry value SystemDB of the registry key :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines
to the path of the workgroup file but this causes other problems (like with other MS Access apps or Excel).
Is there a better way of doing this?
I haven't done this for a while, nor in recent versions of SQL server, but I seem to remember that when you add a link to a Jet database it provides the opportunity to define the workgroup, username and password. Certainly if you're using ODBC, that's part of the basic ODBC driver for Jet.