Hope you can assist me with an issue I am facing. This is a lengthy one to provide context. In short, my Windows auth access to a SQL Server 2008 R2 database fails as it appears to be trying to access the database as 'NT AUTHORITY\ANONYMOUS LOGON' and not the current user.
Here's my scenario: server farm with multiple servers running standalone SQL Server databases on which a number of PowerShell scripts need to be run, which connect to the databases and run some queries & based on the queries, make some updates to some database tables. We're failing at Windows auth login to the database (which works fine with SQL Server Mgmt Studio v10).
It looks something like this:
win7pc PS C:> Enter-PSSession -ComputerName winsvr2k8r2
[winsvr2k8r2]: PS c:\users\svs_acct1>
[winsvr2k8r2]: PS c:\users\svs_acct1> Set-Location C:
NB: there is a script directory that is part of the $env:PATH set in the profile
[winsvr2k8r2]: PS c:\users\svs_acct1> . .\users\svs_acct1\bin\Run-AdminTasks
Script output
Loading AD module ...
Setting Global Variables ...
I am user: domreff1\dbappuser
Initiating DB Connection using windows auth to: sTango # hgr23992\atr77504
with connect string ...
Data Source=hgr23992\atr77504;Initial Catalog=sTango;Integrated Security=SSPI
ERROR
Exception calling "Open" with "0" argument(s): "Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'."
At C:\users\svs_acct1\bin\Run-AdminTasks:21 char:20
+ $SqlConnection.open <<<< ();
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
The relevant DB connection elements in the script:
$SQLServer = "hgr23992\atr77504";
$SQLDBName = "sTango";
$SQLDBUser = [Security.Principal.WindowsIdentity]::GetCurrent().Name;
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Data Source=$SQLServer;Initial Catalog=$SQLDBName;Integrated Security=SSPI"
$SqlConnection.open();
I have trawled through various posts and tried connection string a number of different ways e.g.
Data Source=$SQLServer;Initial Catalog=$SQLDBName;Integrated Security=[Yes|True|SSPI]
with no joy.
Any ideas on what the issue may be and why the DB connection seems to be reflecting a different context/user to what I am running the script as?
The problem is kerberos auth and the missing delegation of the token.
You could enable CredSSP auth for powershell (on client & server side). Please do this only over SSL otherwise you're vulnerable for an MITM.
check
https://msdn.microsoft.com/en-us/library/ee309365(v=vs.85).aspx
Related
I am trying to use Analysis Services Cmdlets to process partitions on a Power BI Premium Model. My PowerShell script works fine when run from ISE, the command line, and when scheduled using windows task scheduler; however, when I try to schedule the PowerShell script using a SQL Server 2019 Agent job using a step type of
Operating System (CmdExec)" the following error message is encountered.
Message Executed as user: MyDomain\MyUser. Invoke-ProcessPartition : The
connection string is not valid. At
C:\Users\MyUser\Desktop\PS1\SSAS\wtf.ps1:15 char:11 + $asResult =
Invoke-ProcessPartition -Credential $UserCredential -Server...+
CategoryInfo : NotSpecified: (:) [Invoke-ProcessPartition],
ConnectionException + FullyQualifiedErrorId :
Microsoft.AnalysisServices.ConnectionException,Microsoft.AnalysisServices.PowerShell.Cmd
lets.ProcessPartition.
I have followed the steps in this blog article to setup the job. The same windows user is used in all three run scenarios. The SQL server is my local development SQL server of which the windows user is SA on the SQL Server and Windows Admin. The same machine the SQL Instance is on is being used for successfully executing the other three ways of running the PS scripts, (ISE, Command Line, & Windows Task Scheduler)
If I run the following from the command line on the same machine as the SQL server, my local host, the PowerShell script runs successfully.
PowerShell -File "C\Users\MyUser\Desktop\PS1\SSAS\wtf.ps1"
Below is my PowerShell script modified to be as small as possible to demonstrate issue and of course sensitive information redacted. Thanks in advance for any help, I'm at a loss at how to proceed. I really need this to work from the SQL agent so I don't have to guess when steps that the processing depends on have completed.
$ErrorActionPreference=”Stop”
Import-Module "SqlServer"
$User = "MyUser#MyDomain.com"
$PWord = ConvertTo-SecureString -String "MyPassword" -AsPlainText -Force
$UserCredential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
$server = "powerbi://api.powerbi.com/v1.0/myorg/MyWorkspace"
$db = "MyModel"
$asResult = Invoke-ProcessPartition -Credential $UserCredential -Server $server -PartitionName "DimDate" -TableName "DimDate" -Database $db -RefreshType "Full"
The step code in my job is:
powershell -File "C:\Users\MyUser\Desktop\PS1\SSAS\wtf.ps1"
UPDATE:
I have discovered that if I target an on-prem SSAS server, the exact same code, with the exception of the server variable, does work using the SQL Agent method, but of course switching to on-prem is not what I desire.
UPDATE 2:
When I right click on a job within SSMS, and click "Start PowerShell" this opens up a SQL Server PowerShell Window. If I try executing the script this way I get the below error message. The account being used does not have MFA enabled.
Unable to obtain authentication token using the credentials provided.
If your Active Directory tenant administrator has configured
Multi-Factor Authentication or if your account is a Microsoft Account,
please remove the user name and password from the connection string,
and then retry. You should then be prompted to enter your credentials.
If I don't pass a credential to the Invoke-ProcessPartition command using the SQL Server PowerShell window, I get prompted for credentials and the call works. Of course I can't use this as a workaround because I need it to run unattended.
I also tried opening PowerShell ISE as the account being used for authentication to the Workspace in the PS script and it also gives the same error as the SQL Server Agent Job does.
The connection string is not valid.
I have found a solution to the issue. The resolution was twofold.
First problem was that when PowerShell was being run from the SQL Server Agent, the Version of the SqlServer module was an older outdated version. I found this out by executing a ps1 file from the SQL Server Agent Job using the following code and looking in the job history results.
Get-Command -module sqlserver invoke*
I tried running
Install-Module sqlserver -AllowClobber -Scope AllUsers
as an admin but it did not update the SqlServer module the SQL agent was running. Instead I created a ps1 file that simply runs
Install-Module sqlserver -AllowClobber -Scope CurrentUser -Force
and called the script using a SQL Agent CMD task and this updated the SqlServer module version. After this I started getting a more useful error message:
Unable to obtain authentication token using the credentials provided.
If your Active Directory tenant administrator has configured
Multi-Factor Authentication or if your account is a Microsoft Account,
please remove the user name and password from the connection string,
and then retry. You should then be prompted to enter your
credentials
With this new error message, I decided to try an alternate way of supplying credentials by utilizing Azure Service Principals. This new method resulted in success from all PowerShell methods including SQL Server Agent Job. The steps implemented are outlined in this Power BI Documentation.
The final PS code looks like this.
$ErrorActionPreference=”Stop”
Import-Module "SqlServer"
$AppId = "AAD_App_Registration_Application_Client_Id"
$TenantId = "AAD_App_Registration_Directory_Tenant_Id"
$AppSecret = "AAD_App_Registration_CertificatesAndSecrets_ClientSecret"
$PWord = ConvertTo-SecureString -String $AppSecret -AsPlainText -Force
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $AppId, $PWord
Invoke-ProcessPartition -Server "powerbi://api.powerbi.com/v1.0/myorg/MyModel" -PartitionName "DimDate" -TableName "DimDate" -Database "MyModel" -RefreshType "Full" -ServicePrincipal -ApplicationId $AppId -TenantId $TenantId -Credential $Credential
On my computer I have only SQL Server Management Studio installed.
I use runas.exe /netonly /user:myDomain\myUser powershell.exe to open Powershell console (I need to authenticate to SQL Server using Windows Authentication).
Then I connect to SQL Server DB using following code:
$myConnectionString = "Server=$($serverName);Database=$($dbName);Trusted_Connection=True;"
$SQLConnection = New-Object System.Data.SQLClient.SQLConnection
$SQLConnection.ConnectionString = $myConnectionString
$SQLConnection.Open()
$SQLCommand = New-Object System.Data.SqlClient.SqlCommand
$SQLCommand.CommandText = "SELECT top 2 * FROM [myTable]"
$SQLCommand.Connection = $SQLConnection
Unfortunately when I type:
$SQLCommand.ExecuteReader()
I receive an error:
An error occurred while enumerating through a collection: Could not
load file or assembly 'Microsoft.SqlServer.Types, V ersion=10.0.0.0,
Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its
dependencies. The system cannot find t he file specified.. At line:1
char:1
+ $SQLCommand.ExecuteReader()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Data.Common.DbEnumerator:DbEnumerator) [], RuntimeException
+ FullyQualifiedErrorId : BadEnumeration
After searching the Internet, I thought that I should install 'SQLSysClrTypes' (from SQL Server Feature Pack).
Thus I downloaded it, but it seems that I have this component installed on my local computer (installer allows me to repair or remove this component only).
What should I install to be able to query the DB from Powershell? On which computer should I install that computer?
EDIT:
When I log into the server through RDP (mstsc), and use following connection string:
$myConnectionString = "Server=.;Database=$($dbName);Trusted_Connection=True;"
I do not experience such issues - ExecuteReader() returns results.
You don't need to install any additional tools or libraries to query MS SQL Server from PowerShell, assuming you are running Windows 7 or newer.
The installed .NET framework has all ADO.NET components required to do this.
If you get an error, something is wrong with your script or your environment.
I am sure that there must be a better solution, thus I will not mark this response as an answer...
I checked the content of C:\Windows\assembly\GAC_MSIL\Microsoft.SqlServer.Types path and discovered that I have Microsoft.SqlServer.Types.dll for versions 12, 13 and 14.
Thus I just copy-paste mentioned file for version 10.0.0.0__89845dcd8080cc91 from the server to my computer...and it works
So, it seems that somewhere it's hardcoded to use this specific version of Assembly when connecting to SQL Server from Powershell (?)
I've got an installer that creates or updates a database associated with a website. We originally wrote the installer for Microsoft Server 2008 R2, and SQL Server 2008. We've updated to Microsoft Server 2016, and SQL Server 2016 and I now get failures with the dacpac.
I've updated the DAC framework on the system, but the issue persists. The specific part that fails is in a PowerShell script.
New-Object : Cannot find type [Microsoft.SqlServer.Management.Dac.DacStore]: verify that the assembly containing this
type is loaded.
At C:\Users\Administrator\AppData\Local\Temp\2_ir_sf_temp_3\UnregisterDataTier.ps1:29 char:13
+ $dacstore = New-Object Microsoft.SqlServer.Management.Dac.DacStore($s ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
The section of code (line 29 is the final line):
If (!$uid -And !$pwd)
{
$serverconnection.ConnectionString = "Server = $server; Database = $database ; Integrated Security = True;"
}
Else
{
$serverconnection.ConnectionString = "Server = $server; Database = $database ; Integrated Security = False; User ID = $uid; Password = $pwd;"
}
$dacstore = New-Object Microsoft.SqlServer.Management.Dac.DacStore($serverconnection)
I've been trying everything I can find with others getting the same error message, but it doesn't seem to apply to my situation. I am assuming there was some minor change somewhere that I just cannot locate.
This works perfectly on 2008, but I cannot find what might have changed that causes this error.
Hmm are you running this directly on the SQL 2016 server (or on a computer with only the 2016 tool set?). According to this MS Social page, the DAC library was deprecated starting with SQL 2012. You should be able to use the SMO libraries or other .NET libraries to create the connection string at least. However you may need to refactor your script a little for some of your commands.
I am putting together some powershell scripts to execute SQL commands against SQL Server and need to specify the windows account to use in the connectionstring. I have tried the following which does not work.
$SQLServer = ".\sqlexpress"
$SQLDBName = "dbname"
$uid ="domain\user
$pwd = "password"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = false; User ID = $uid; Password = $pwd;"
$SqlCmd.Connection = $SqlConnection
$SqlConnection.Open();
.... Execute query...
I get the following error.
Exception calling "Open" with "0" argument(s): "Login failed for user
'Domain\user'.
I was lead to understand that if you specify false on integrated security then is would take the username and password and connect using the corresponding windows account.
For me this is failing to connect. Am I missing something here ?
Many thanks
Darren
Another way to tackle this would be to use the SQL PowerShell Module (SQLPS) which can be obtained by installing "Management Tools" from the SQL Management Studio Installer. By default, when using Invoke-Sqlcmd it will connect as the windows account that initiated the PowerShell instance. If you wish to run as another windows account other than the one you are signed in with, you would shift + right click PowerShell and choose option to "run as different user".
Once Module has been installed, you can import module by executing:
Import-Module SQLPS
Next you would execute your query like the following:
Invoke-Sqlcmd -ServerInstance "ServerName\Instance" -Database "DatabaseName" -Query "Some Query Here"
While entirely optional, I would recommend adding -Verbose as this will show you output just as you would see in Sql Management Studio.
Hope this helps.
We are running deployment scripts using pstrami. Part of the deployment is to execute database migrations. The migrations are using an connection string with Integrated Security.
When the script executes on the remote machine the migrations fail with a sql error saying Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'
The person executing the script is a domain administrator. Other deployments that we run execute the remote scripts with the user who started the process.
The problem is that the credentials are not hopping to SQL Server for integrated security. You need to do the following:
On the server (the one that is making the SQL Server connection, as administrator run:
Enable-WSManCredSSP -Role server
On the client machine, as administrator run:
Enable-WSManCredSSP -Role client -DelegateComputer YOUR_SERVER_NAME
To open this up to all servers, you can run:
Enable-WSManCredSSP -Role client -DelegateComputer *
Finally, your invoke command make sure you run -authentication credssp. An example:
invoke-command -computername $remoteServer -authentication credssp -scriptblock { write-host "hello!" } -credential $credentials
This is the scenario:
You run the pstrami(deployment) script from desktopA. The script pushes your installation files to serverA. Then on serverA the scripts are run remotely as the person inititating the script from desktopA. One of the steps is to run a sql database upate with fluentmigrator using a connection string paramter using "integrated security" and the database is on serverB.
Connection string example:
$migration_db_connection = Data Source=serverB;Initial Catalog=PropertyDb;Integrated Security=SSPI;
.\migrate.exe /conn "$migration_db_connection" /db SqlServer /a $migration_assembly /profile DEBUG
Pstrami uses the powershell command invoke-command which uses the account you are running the script under as the default user. So, what happens is that when you run the script from desktopA as "jonDoe" it then authenticates on serverA. So your pstrami scripts run under "jonDoe" on serverA. When you execute the fluentmigrator script on serverA as "jonDoe", fluentmigrator returns an error Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'. In IIS, you run into an interesting situation when you need to access another resource off of the IIS server and certain fairly common situations occur. When using Integrated Security, anonymous access is disabled, and impersonation is turned on, a Windows security measure kicks in and doesn't allow your site to access resources on any network servers. (http://weblogs.asp.net/owscott/archive/2008/08/22/iis-windows-authentication-and-the-double-hop-issue.aspx)
This is how I got around the Windows Authentication and the Double Hop problem I ran into. Run your migration scripts directly on your sql database server and include it as a server target in your pstrami environments.
Example:
Environment "dev" -servers #(
Server "serverA" #("InstallWeb")
Server "serverB" #("RunMigrations")
)
More on Double Hop
http://www.spdoctor.net/Pages/message.aspx?name=login-failed-for-user-bdc
http://www.sqlservercentral.com/blogs/sqlsandwiches/2011/06/20/double-hop-of-doom/
I am not able to comment on your question and posting this as an answer. I will update the same later.
It may be due to SQL Server not having the login account for your windows login account. If that is the problem please add the logged in user to the SQL Server in the remote machine.
If this is already addressed, then you have the option of giving Rights as DB_Owner to " NT AUTHORITY\ANONYMOUS LOGON " on the SQL Server as well as on the specific database you are using.