Can't create linked server to Snowflake - sql-server

I followed all the instructions I could find:
Installed latest Snowflake 64bit ODBC driver to my SQL Server VM
Created system dsn for it (filled in User, Server, Database, Schema, Warehouse, Role and Tracing fields)
In SQL server, for the MSDASQL linked server provider, enabled following parameters: Nested queries, Level zero only, Allow inprocess, Supports 'Like' Operator
Created linked server following instructions
Provider=Microsoft OLE DB Provider for ODBC drivers
Data source: name of system DSN I created
Security:
mapped local login 'NT AUTHORITY\SYSTEM' to remote username and password (they work when I connect to Snowflake via web browser)
click 'Be made using the login's current security context'
when clicking ok, I get the following error

In the security tab of the linked server:
you have mapped 'NT AUTHORITY\SYSTEM' (is this the sql service account?) to remote username and password.
For any other login not in the list you have selected Be made using the login's current security context
You connect to sql server using a windows login or a sql server login. Assume you either use domainxyz\rick or username: sqlrick and password: rick1212.
When you try to use the linked server, both possible logins (domainxyz/rick or sqlrick) are not mapped to a remote[snowflake] username and password. So sql server passes through the current security context which is either your domainxyz/rick token or the sqlrick username&password. Both do fail for an external server(can they even work?).
From https://learn.microsoft.com/en-us/sql/relational-databases/linked-servers/create-linked-servers-sql-server-database-engine
Be made using the login's current security context
Specify that a connection will be made using the current security context of the login for logins not defined in the list. If connected to the local server using Windows Authentication, your windows credentials will be used to connect to the remote server. If connected to the local server using SQL Server Authentication, login name and password will be used to connect to the remote server. In this case a login with the exact same name and password must exist on the remote server.
You could either map your login to the remote snowflake username&password, or choose
For a login not defined in the list above, connections will:
Be made using this security context and fill in the username&password for snowflake in the boxes.
/*
snowflake server=xyz12345.west-europe.azure.snowflakecomputing.com
snowflake user= testuser
snowflake password = Testuser1
*/
--system DSN for snowflake named SNOWFLAKEDSN [SnowflakeDSIIDriver, User: testuser, Server:xyz12345.west-europe.azure.snowflakecomputing.com, Database:DEMO_DB, Tracing:4 (default)]
--Note: Attempting any of the commands with a wrong password could lock temporarily the snowflake account. tread carefully
--snowflake without linked server
--openrowset using dsn
SELECT *
FROM OPENROWSET('MSDASQL', 'DSN=SNOWFLAKEDSN;UID=testuser;PWD=Testuser1', 'select cast(TABLE_NAME as varchar(100)) as tablename from demo_db.information_schema.tables');
--openrowset using dsn2 , format= provider, DSN;uid;password, query
SELECT *
FROM OPENROWSET('MSDASQL', 'SNOWFLAKEDSN';'testuser';'Testuser1', 'select cast(TABLE_NAME as varchar(100)) as tablename from demo_db.information_schema.tables');
--openrowset without dsn
SELECT *
FROM OPENROWSET('MSDASQL', 'DRIVER=SnowflakeDSIIDriver;SERVER=xyz12345.west-europe.azure.snowflakecomputing.com;UID=testuser;PWD=Testuser1', 'select cast(TABLE_NAME as varchar(100)) as tablename from demo_db.information_schema.tables');
GO
--linked server using DSN
EXEC master.dbo.sp_addlinkedserver #server = N'SNOWFLAKE_WITH_DSN', #srvproduct=N'', #provider=N'MSDASQL', #datasrc=N'SNOWFLAKEDSN';
/*every login of the sql instance connects to snowflake as testuser*/
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'SNOWFLAKE_WITH_DSN',#useself=N'False',#locallogin=NULL,#rmtuser=N'testuser',#rmtpassword='Testuser1';
--linked server without DSN, name of linked server is SNOWFLAKE_WITHOUT_DSN
EXEC master.dbo.sp_addlinkedserver #server = N'SNOWFLAKE_WITHOUT_DSN', #srvproduct=N'', #provider=N'MSDASQL', #provstr=N'DRIVER=SnowflakeDSIIDriver;SERVER=xyz12345.west-europe.azure.snowflakecomputing.com';
/*every login of the sql instance connects to snowflake as testuser*/
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'SNOWFLAKE_WITHOUT_DSN',#useself=N'False',#locallogin=NULL,#rmtuser=N'testuser',#rmtpassword='Testuser1';
--linked server without DSN, hardcoded snowflake creds in the provider string (at own risk)
/*
EXEC master.dbo.sp_addlinkedserver #server = N'SNOWFLAKE_WITHOUT_DSN_HARDCODED_CREDS', #srvproduct=N'', #provider=N'MSDASQL', #provstr=N'DRIVER=SnowflakeDSIIDriver;SERVER=xyz12345.west-europe.azure.snowflakecomputing.com;UID=testuser;PWD=Testuser1';
/*creds hardcoded in the connection string, logins use their own security context */
/* caveat: this worked ok for windows authenticated logins. sql authenticated logins could not use the linked server, not tested with msdasql in process... */
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'SNOWFLAKE_WITHOUT_DSN_HARDCODED_CREDS',#useself=N'True',#locallogin=NULL,#rmtuser=NULL,#rmtpassword=NULL;
*/

Related

Can only see tables on linked server via administrator. Not as SQL server user

I have two database servers. One on the office computer and one on the webserver. There is a secure encrypted tunnel between the two computers over the internet.
A SQL Server user has been set up on the webserver pc to allow access to the tables I need.
On the office pc there is a local account that needs access to those linked tables.
A linked server is setup between the computers. From the sysadmin interface in SQL Server Management Studio I can browse the tables at free will on the linked server.
but if I log in as the SQL Server user and I try test connection
===================================
The test connection to the linked server failed.
===================================
An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)
------------------------------
Program Location:
at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(String sqlCommand, ExecutionTypes executionType)
at Microsoft.SqlServer.Management.Smo.ExecutionManager.ExecuteNonQuery(String cmd)
at Microsoft.SqlServer.Management.Smo.LinkedServer.TestConnection()
at Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.LinkedServerConnectionTest.Invoke()
===================================
Access to the remote server is denied because no login-mapping exists. (.Net SqlClient Data Provider)
------------------------------
For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft%20SQL%20Server&ProdVer=11.00.5058&EvtSrc=MSSQLServer&EvtID=7416&LinkId=20476
------------------------------
Server Name: SERVER\INSTANCE
Error Number: 7416
Severity: 16
State: 2
Procedure: sp_testlinkedserver
Line Number: 1
------------------------------
Program Location:
at Microsoft.SqlServer.Management.Common.ConnectionManager.ExecuteTSql(ExecuteTSqlAction action, Object execObject, DataSet fillDataSet, Boolean catchException)
at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(String sqlCommand, ExecutionTypes executionType)
What have I tried so far
Adding the local and remote user details to the Linked server properties window.
Adding default security context "Be made using this security context"
How can I set it up so the SQL Server user can use the linked server?
The problem lies in the fact that the user ID needs to be defined in the remote connection string.
From https://blogs.technet.microsoft.com/mdegre/2011/03/10/access-to-the-remote-server-is-denied-because-no-login-mapping-exists/
Cause: When creating a linked server with the parameter #provstr and
you use a local SQL Server non-admin or non-Windows account, you have
to add the parameter “User Name” into the #provstr
Resolution : Add “User ID=Username” into the provider string on your
linked server
EXEC master.dbo.sp_addlinkedserver #server = N’LinkServerName’,
#provider=N’SQLNCLI’,#srvproduct = ‘MS SQL Server’,
#provstr=N’SERVER=serverName\InstanceName;User ID=myUser‘
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname = N’LinkServerName’,
#locallogin = NULL , #useself = N’False’, #rmtuser = N’myUser’,
#rmtpassword = N’*****’
In total my setup string looked like this(with extra details for setting up the connection over the internet.
EXEC master.dbo.sp_addlinkedserver #server = N'LINKEDSERVERNAME', #srvproduct=N'SQL_SERVER', #provider=N'SQLNCLI', #provstr=N'SERVER=SERVER\INSTANCE;User ID=webuser', #datasrc=N'www.domain.com'
Small note, my webserver doesn't have an instance name, so I left the '\INSTANCE' part out of the connection string build up.
Note 2: The documentation states #srvproduct='MS SQL Server' but my 2012 sql server only accepts SQL_SERVER instead.

Login failed when querying linked server

I am trying to create a linked server in SQL Server:
--Create the link to server "uranium"
EXEC master.dbo.sp_addlinkedserver
#server = N'uranium',
#srvproduct=N'',
#provider=N'SQLNCLI'
--Add the catch-all login with SQL Server authentication
EXEC master.dbo.sp_addlinkedsrvlogin
#rmtsrvname=N'uranium',
#useself=N'False',
#locallogin=NULL,
#rmtuser=N'BatteryStaple',
#rmtpassword='Horsecorrect'
And it creates fine. But any attempt to query the linked server, e.g.:
SELECT * FROM uranium.Periodic.dbo.Users
results in
Msg 18456, Level 14, State 1, Line 1
Login failed for user 'BatteryStaple'.
Except i know the credentials are correct:
Login: BatteryStaple
Password: Horsecorrect
because i can login when i connect directly using SQL Server Management Studio, or any other technology that is able to connect to a database.
Bonus Reading
Login Failed for linked server (he forgot to call sp_addlinkedsrvlogin)
Why am I getting a “login failed” when creating this linked server? (he's trying to use integrated authentication)
MSDN Blogs: SQL Linked Server Query failed with “Login failed for user …” (he's trying to make integrated authentication work)
Note: New SQL Server 2014 install. Every existing SQL 2000, 2005, 2008, 2008 R2 can communicate to their uranium linked server. I'm certain it is related to Microsoft's frustrating broken by default policy.
The issue is that the SQL Server Management Studio interface creates the linked server using the OLEDB Provider:
This is equivalent to the original T-SQL:
--Create the link to server "uranium"
EXEC master.dbo.sp_addlinkedserver
#server = N'uranium',
#srvproduct=N'', #provider=N'SQLNCLI'
The fix is to create the linked server as SQL Server:
--Create the link to SQL Server "uranium"
EXEC master.dbo.sp_addlinkedserver
#server = N'uranium',
#srvproduct=N'SQL Server'
Shouldn't matter. Probably a regression in Microsoft SQL Server 2014 12.0.4213.0. Might be fixed in a service pack - if there is one.
But there it is; solved.
Old post, but might be useful still. In my case it was that only Windows Authentication was set. Setting authentication for both Windows and SQL Server on the linked server fixed it.
The issue for me was this: Since I was trying to connect to instance via servername\instancename - ALL my instances were running on port 1433 so the "Add Linked Server" was actually connecting to the default instance - and the login was failing.
Go to SQL Configuration Manager
Click on Protocols for [instancename]
Open TCP/IP properties and be sure it's enabled AND flip to the "IP Addresses" Tab and change the port on ALL IPs that you are using for your linked server IP is (a) active and (b) using a unique port - like 14333 (this was important as my VPN IP was not "active".
You may have to do this for both 32 and 64 if your machine is running both
DONT FORGET TO STOP and START THE INSTANCE
This is the fix

SQL Server 2012 - Openrowset - User without sysadmin

Environment :
Server : Windows Server 2012
SQL Server : SQL Server 2012
I want to use openrowset in my production environment without granting sysadmin to the user. saw a lot of posts about this issue but non seem to provide a solution to mine.
I performed the following steps:
Created a non administrator windows account
Created a windows authentication login in my database (not sysadmin)
Enabled 'show advanced options','ad hoc distributed queries'
Verified 'Disallow adhoc access' is disabled in the provider (key does not exist in the registry)
Enabled driver
USE [master]
GO
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
Changed the user running the SQL server service to be Administraor
Granted full permissions on the TEMP , TMP directory of the Administrator to the user created on Step1.
Whenever I run the query:
SELECT *
FROM OPENROWSET('MICROSOFT.ACE.OLEDB.12.0','Excel 8.0;Database=c:\temp\xxx.xls;','SELECT * FROM [xxx$]')
I get:
Ad hoc access to OLE DB provider 'MICROSOFT.ACE.OLEDB.12.0' has been denied. You must access this provider through a linked server.
It does not seem to even try to access the file because whether it is there or not I get the same error. When I run it with the sysadmin user it works and when I try to query a non existing file I get error it can't find it in oppose to the non sysadmin user.
Maybe I am missing a permission on different directory or the the non sysadmin user is missing other permission.
Can you please advise?
Thanks
Doron

SQL Server 2012 classic asp connection string

I have a SQL Server 2012 Express installation with a new DB called BRD that I have created. I have also created a test table (tempDemo), and a test stored procedure (getStList) in the BRD database. The stored procedure works when I run it in the query window so I believe the table and stored procedure are legit. The SQL Server is set to "SQL Server and Windows Authentication mode".
I then attempted to create a Classic ASP page that then connected to the SQL Server using the following connection string:
objConn.ConnectionString="Provider=SQLOLEDB;Server=XPSI7\SQLEXPRESS;Database=BRD;Integrated Security=SSPI;"
This fails with the following message:
"Microsoft OLE DB Provider for SQL Server error '80004005'
Cannot open database "BRD" requested by the login. The login failed."
When I change the database to MASTER instead of BRD the ASP page does not error out. I'm just testing the connection string by opening it and then closing it, but it appears to work.
I've looked at the security settings for MASTER and BRD in the Object Explorer, but have failed to notice a difference. I've also looked at the IIS_IUSRS for the folders, but no difference either - not sure if this is necessary anyway.
SQL Server authenticates your login at the server level. Then it tries to open the database you've asked to connect to. At this point, you need to either map a database-level user to the server-level login, or use a server-level login that inherently has sufficient privileges to use the database.
A simple (but not secure) way to demonstrate this using SQL Server Authentication:
USE master;
GO
CREATE LOGIN foo
WITH PASSWORD = 'bar', CHECK_POLICY = OFF;
GO
USE BRD;
GO
CREATE USER foo FROM LOGIN foo;
GO
EXEC sp_addrolemember N'db_owner', N'foo';
GO
Now in your ASP connection string, use:
objConn.ConnectionString = "Provider=SQLNCLI;Data Source=XPSI7\SQLEXPRESS;Initial Catalog=BRD;User ID=foo;Password=bar;"
You can also map whatever login you're using to a database user simply doing:
USE BRD;
GO
CREATE USER [YourDomain\IIS_IUSRwhatever]
FROM LOGIN [YourDomain\IIS_IUSRwhatever];
GO
That will grant them access to the database, but it will be up to you to decide what permissions to grant. This assumes that you are allowing anonymous access to the web server; if IIS is challenging and accepting Windows authentication, you'll need to do the above for the user(s) that will be submitting their credentials. In either case you should be able to continue using the connection string you have now.
Try the following connection string:
strConnection = "Provider=SQLNCLI10;Server=server_name;Database=" & BD_REMOTE_INITIAL_CATALOG & ";Uid=" & BD_REMOTE_USER_ID & "; Pwd=*****;"

sp_addlinkedserver syntax

I would like to make a copy of what's on my remote server at xxx.safesecureweb.com.
How do I connect to it from my local SQL Server?
Is the syntax something like:
sp_addlinkedserver
#server='PRODUCTION',
#provider='xxx.safesecureweb.com',
#Username='myUsername',
#Password='myPassword'
What I'm thinking of doing is writing a bunch of insert statements like:
INSERT INTO Test.Table
SELECT * FROM Production.Table
You do not specify the remote user and password in the linked server definition. Linked servers have a separate object that mapps the login of users connected to the local server (the 'locallogin') with remote logins. See Security for Linked Servers. For example, the following maps all local logins on the linked server to the specified MyUserName SQL Login:
exec sp_addlinkedserver 'xxx.safesecureweb.com';
exec sp_addlinkedsrvlogin 'xxx.safesecureweb.com'
, 'FALSE', NULL, 'myUserName', 'myPassword';
You can only map with user/password a remote SQL login. Remote Windows logins (trusted authentication) must use integrated authentication and configure the server for constrained delegation.
Provider should be the client provider you want to use to connect. #datasrc is the servername to connect to.
sp_addlinkedserver
#server='PRODUCTION',
#provider='SQLNCLI', -- sql native client.
#Username='myUsername',
#Password='myPassword',
#dataSrc = 'xxx.safesecureweb.com'
Then, when querying, I believe you need to use a four part name fot the table:
INSERT INTO Test.Table
SELECT * FROM Production.mydatabase.dbo.Table
http://msdn.microsoft.com/en-us/library/ms190479.aspx

Resources