Unable to Process Partition in Power BI Premium Model Using SQL Server Agent Powershell CmdExec Step - sql-server

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

Related

Windows password does not work for Powershell Credential Request

I am aware I can set up Powershell credentials Get-Credential for my own scripts. But when I use the following command Get a SQL Server instance on a computer in a PS terminal:
Get-SqlInstance -Credential laptop-ql9k5dk6\david -ServerInstance "laptop-ql9k5dk6\sqlexpress2"
I expect that I am going to be asked for my Windows password.
Here is my thinking:
Logging in to my SQL Server instance (laptop-ql9k5dk6\david) via MS SQL Server Management Studio (using Windows Authentication) uses my already logged on status. Otherwise I would need my Windows password.
Since my script is asking for a password for laptop-ql9k5dk6\david; I think it must be my Windows password?
So. Why does my Windows Password fail when my PowerShell one-liner (shown above) asks me for a password?
PowerShell credential request
Enter your credentials.
Password for user laptop-ql9k5dk6\david: **************
Get-SqlInstance: Failed to connect to server laptop-ql9k5dk6\sqlexpress2.
On MSSM I can also login via SQL Login but for that the username is different from the Windows Authentication user above.
Note: My current Windows password is good. I use it regularly without making mistakes/leaving CAPs on etc.
$role = "sql"
$user = read-host "user for $role"
$pwd = read-host "password:" -AsSecureString
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $user, $pwd
Get-SqlInstance -Credential $cred -ServerInstance "laptop-ql9k5dk6\sqlexpress2"
perhaps the cmdlet does not support Integrated Security=true;
Incorrect Password: One possibility is that you may be entering the wrong password. Double-check to ensure that you are entering the correct password for your Windows account.
Locked Account: If you have entered the wrong password too many times, your account may become locked. This can prevent you from accessing your account until it is unlocked. You can try unlocking your account by following the steps provided by your system administrator.
Expired Password: It is also possible that your Windows password has expired. In this case, you will need to reset your password before you can log in. You can reset your password by following the steps provided by your system administrator.
Credential Manager: If you are running your PowerShell script from a different machine or domain, your Windows credentials may not be recognized. In this case, you can try storing your credentials in the Windows Credential Manager. You can do this by running the cmdkey command in the command prompt or PowerShell.
System Permissions: If you are trying to run a PowerShell script that requires elevated privileges, you may need to run PowerShell as an administrator. Right-click on the PowerShell icon and select "Run as administrator".

How to Restart SQL Reporting Service with Account and Password?

In Windows 2003 Server, I have a service running called 'SQL Server Reporting Services'.
This service will Stop at times, and when I try to Start it, it would give an Error as:
'Error 1069: The Service did not start due to a logon failure.'
After which, I would go to Properties -> Logon -> this account -> Give Username and Password.
After Applying the Changes, I can start the Service.
How do I go about writing a Script which would Automate this setting username and password and starting the Service? Also, is there any way to check if the Service is in a Run State and if not, script the logon step and start it?
Thank you.
I would suggest installing powershell for server 2003.
Have a look at this Powershell script to change service account.
You can user get-service to find if the service is running.
Something like the following could help. (For a Windows machine)
----> Refresh_SSRS.ps1
Stop-Service “SQL Server Reporting Services (SQLSRV)”
Start-Service “SQL Server Reporting Services (SQLSRV)”
$wc = New-Object system.net.webClient$wc
$cred = [System.Net.CredentialCache]::DefaultNetworkCredentials
$wc.Credentials = $cred
$src = $wc.DownloadString(“http://ComputerNamexxx/Reports_xxxxxx/Pages/Folder.aspx“)
---->Run in Task Scheduler - on a regular occurance - where the user account can be assoicated:
Powershell.exe
-ExecutionPolicy Bypass -File C:\commands\Refresh_SSRS.ps1

Connecting to SQL Server 2012 (using Windows auth) via powershell Enter-PSSession

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

Remotely joining computer to domain using powershell and WMI

For a CI/CD environment I am building a PowerShell script to create an new Hyper-V VM which is basically a clone of a 'base-vm'. This base-vm is not a member of the domain, it is a Windows workgroup member.
When trying to add the computer to the domain I have the following issue, the script displayed below works when run directly on the target machine which is the Hyper-V host (running under an administrative account) but not when being run from the build server (Jenkins).
The process is as shown in the following scheme:
And the script part which is failing is the following:
Invoke-Command -Session $remoteSession -Scriptblock {
Rename-Computer -NewName $args[0] -Restart
} -ArgumentList $vmSettings.ComputerName
Start-Sleep -s 30
$newVmRemoteSession = New-PSSession -ComputerName $vmSettings.ComputerName -Credential $credentials
Invoke-Command -Session $newVmRemoteSession -Scriptblock {
Add-Computer -Domainname myfunny.domain -Credential $args[0] -Restart
} -ArgumentList $domainAdminCredentials
Remove-PSSession $newVmRemoteSession
Remove-PSSession $remoteSession
Write-Host "Done creating new VM"
The $remoteSession variable contains a remote PowerShell session based on the local administrator crendentials.
The $newVmRemoteSession variable contains an remote session to the renamed virtual machine with the local administrator crendentials.
The error I recieve while running this script via a build-job:
[base-vm] Connecting to remote server base-vm failed with the following error message : WinRM cannot complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for public profiles limits access to remote computers within the same local subnet. For more information, see the about_Remote_Troubleshooting Help topic.
The command which throws the exception is:
Invoke-Command -Session $newVmRemoteSession -Scriptblock {
Add-Computer -Domainname myfunny.domain -Credential $args[0] -Restart
} -ArgumentList $domainAdminCredentials`
I have been looking for the solution for this problem, but I cannot find the error. First I thought it had to do with trusted relationships between the build server and the virtual machine but when I used WinRM to add that relationship the build still fails.
I used: winrm s winrm/config/client '#{TrustedHosts="*"}' to add the relationship.
UPDATE: The other thing I did is running the script with the same user as the build server did. This gave me the same error as above. The strange thing is that the user is an local administrator on the server from which the script is being run and is also member of the 'remote management users' group on that server.
UPDATE2: I found out that the issue has to do with Kerberos versus Negotiate authentication. When running a script from a domain joined workstation the script runs under the Kerberos scheme by default and when run from a standalone workstation it runs under the Negotaite scheme, which needs an SPN for what I read from https://msdn.microsoft.com/en-us/library/windows/desktop/aa378748(v=vs.85).aspx.
You're right in that it's probably an auth issue.
PowerShell uses Kerberos for this stuff and is set up for domain joined stuff.
I think you were on the right lines with the trusted hosts addition...
There's an article at http://powershell.com/cs/blogs/tips/archive/2016/01/25/enabling-powershell-remoting-with-ntlm.aspx, which explains how to set it up and uses slightly different syntax to what you've described. Maybe try that?
The computer was not accessible through the domain, so I used CredSSP to connect to it. To enable credssp I had to run the enable-wsmancredssp commandlet on the client and server and had to use the gpedit.msc addin to configure access.

Execute SQL command with powershell and specifying the domain account

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.

Resources