JiraPS printing linebreaks instead of results - powershell

I have a problem when using the JiraPS Module in a script.
When executing the script below I receive a line-break instead of an actual result. The weird thing is, when executing the script twice, once without the Get-JiraProject -Project 'exampleBoard' at the bottom and once with only the Get-JiraProject -Project 'exampleBoard' everything works fine and I get the correct output. When using Get-JiraProject in the script which outputs all projects with read-access I get a line-break for every project.
param ($jirauser)
$ServerURi = 'https://company.atlassian.net'
if (!(
(Get-Module BetterCredentials -ListAvailable) -and
(Get-Module JiraPS -ListAvailable)
)) {
$Force = $True
}
if ($Force) {
# Force the installation of the latest version of the modules
Install-Module -Name BetterCredentials -Scope CurrentUser -AllowClobber -Force
Install-Module -Name JiraPS -Scope CurrentUser -Force
}
# Set Jira server and create session
Import-Module JiraPS -Force
Set-JiraConfigServer $ServerURi
# Get credentials with "BetterCredentials" and store them if they are new
Import-Module BetterCredentials -Force
$cred = Get-Credential -UserName $jirauser -Store
#Session Creation
Write-Output "Creating a session"
$session = New-JiraSession -Credential $cred
if ($session) {
Write-Output $session
}
Get-JiraProject -Project 'exampleBoard'
The output looks as follows:
The value of jirauser is: example#company.com
Creating a session
Username WebSession
-------- ----------
example#company.com Microsoft.PowerShell.Commands.WebRequestSession
I tried the following already:
Running the script inside WSL and PWSH to work around Execution Policies
Using / not using BetterCredentials
Split the code in two (as described above) and ran it twice
Writing the output of Get-JiraProject into a variable and printing the variable instead
Using New-Object System.Management.Automation.PSCredential to create the credentials manually
Sleep for a few seconds after authenticating

Related

Invoke-AzVMRunCommand and Start-Process under specific user on remote VM using Azure Runbook

I need to run Start-Process on a remote VM with specific user account using Azure Powershell Runbook
function Install-Postgres {
$username = "aact-import-vm1\aact-importer"
$password = "ChangeMe!"
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList `
#($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
write-output $cred
# run pg installer
Start-Process "C:\Program Files\WindowsPowerShell\Modules\Install-Postgres\postgresql.exe" -ArgumentList `
"--mode unattended", "--unattendedmodeui none",`
"--prefix `"C:\Program Files\PostgreSQL\10`"", "--datadir `"C:\Program Files\PostgreSQL\10\data`"",
"--superpassword `"ChangeMe!`"",`
"--servicename `"postgres`"", "--serviceaccount `"postgres`"", "--servicepassword `"ChangeMe!`""`
-Wait -Credential $cred;
}
$script = Get-Content Function:\Install-Postgres
Out-File -FilePath Install.ps1 -InputObject $script
#Note that the -ScriptPath should not point to the remote path(in remote vm), it should point to the local path where you execute the command Invoke-AzureRmVMRunCommand
$output = Invoke-AzVMRunCommand -ResourceGroupName $resourceGroupName -Name $vmName -CommandId 'RunPowerShellScript' -ScriptPath Install.ps1
write-output $output.Value
#after execution, you can remove the file
Remove-Item -Path Install.ps1
The script above produces the following error:
Start-Process : This command cannot be run due to the error: Access is denied.
If I run the script above without specific credentials the postgres installer produces this error in the log:
Executing icacls "C:\Windows\Temp/postgresql_installer_1ef9b3f2c6" /T /Q /grant "WORKGROUP\aact-import-vm1$:(OI)(CI)F"
Script exit code: 1332
Script output:
Successfully processed 0 files; Failed processing 1 files
Script stderr:
WORKGROUP\aact-import-vm1**$**: No mapping between account names and security IDs was done.
Please notice that there is symbol $ instead of user name.
However, if I run it on the VM it works fine and produces this line in the log:
Executing icacls "C:\Users\aact-importer\AppData\Local\Temp\2/postgresql_installer_2662c862ff" /T /Q /grant "aact-import-vm1\aact-importer:(OI)(CI)F"
Script exit code: 0
As far as I can see, If I run runbook script remotely without credentials it runs under NTAUTHORITY\SYSTEM that's why there is symbol $ instead of user name in the postgres installer log. If I run it locally it uses proper user and everything works fine.
The question is: how can I specify a user account to run Start-Process on the remote VM?
Same question on msdn https://social.msdn.microsoft.com/Forums/en-US/a7fa0ca8-5cba-42bb-8076-9a8d4a654beb/invokeazvmruncommand-and-startprocess-under-specific-user-on-remote-vm-using-azure-runbook?forum=azureautomation#a7fa0ca8-5cba-42bb-8076-9a8d4a654beb
For those who are interested:
After investigation with MS support they confirmed that runbook (not hybrid) always runs under NTAUTHORITY\SYSTEM

Wait for remote Powershell script to finish

I'm creating a powershell script to import Dynamics NAV Application Objects to my Dynamics NAV 2018 database.
Microsoft is providing a PS cmdlet - Import-NAVApplicationObjects - to do so, but I have trouble to wait for the command to finish.
I have a calling script which does the following
$PSSession = New-PSSession -ComputerName $TargetMachine -Credential $MyCredential
Invoke-Command -Session $PSSession -ArgumentList $Database_Name_user, $MyCredential -ScriptBlock {
$process = Start-Process powershell.exe -Verb RunAs -Wait -PassThru -ArgumentList "-File `"C:\Users\User\Desktop\Database\Import1.ps1`" $args[0]"
$process.WaitForExit()
if ($process.ExitCode -ne 0) {
throw $process.StandardError.ReadToEnd()
}
}
The script Import1.ps1 on my $TargetMachine looks like this
param(
[String]$Database_Name_user
)
try {
$AllFiles = "C:\Users\User\Documents\AllFiles.txt"
$Modules = "C:\GIT\Loading Components\NAVModuleImport.ps1"
$OutputBuffer = import-module $Modules
Import-NAVApplicationObject -Path $AllFiles -DatabaseServer "SQLSRV001" -DatabaseName $Database_Name_user -SynchronizeSchemaChanges "No" -ImportAction "Overwrite" -Confirm:$false | Out-Null
}
catch{
$_ | Out-File "C:\Users\User\Documents\Import1.txt"
}
The file AllFiles.txt has a size of 220 MB and contains more than 7700 Dynamics NAV Application Objects (tables, pages, codeunits and so on).
When I launch the script which executes Import-NAVApplicationObject directly from the remote computer stored in $TargetMachine everything works smootly and the process takes up to 10 to 15 minutes, as expected.
When calling the script as shown in the first code example the output stops for a minute and then says everything is done.
Any help is appreciated, thank you in advance.
Edit: Solution
I noticed that my scripts as shown are working, the Import-NAVApplicationObjects cmdlet just failed.
When I elevate the powershell process on the remote computer and run the import, the cmdlet tried to authenticate as NT-Authority\Anonymous to the database.
Then I passed the credentials of the user that opens the remote PSSession to Import1.ps1 and used the parameters -UserName and -Password of the import cmdlet.
Sadly this process failed again.
Now I tried some things with the user I want to use for authenticating, changing passwords etc and it worked! The password contained a semicolon ; and apparently the import cmdlet was not happy with that.
So my simple solution is: Removing the semicolon from the password.

PowerShell Script fails to execute batch file on Remote server

I have a PowerShell script which works fine on windows server 2016 azure VM but fails to execute the same script from my build agent which is also window server 2016 OS azure VM.
No errors get logged in PowerShell due to which i am not able to figure out what is the reasons?
Is there any Prerequisites that i need to validate or install on the server for executing this script?
Below is the script which execute batch file present on another another VM.
$Username = 'ABC'
$Password = 'XYZ'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
try {
Invoke-Command -ComputerName "ServerName" -credential $cred -ErrorAction Stop -ScriptBlock {Invoke-Expression -Command:"cmd.exe /c 'C:\CI\Demo_CI.bat'"
Write-Host "done"
}
} catch {
Write-Host "error"
}
I believe what you are facing here is a Credential delegation issue, You can try enabling CredSSP in your build agent and the target "ServerName". To know more about credssp , see here, therwise you will have to use psexec in CI.

Trouble calling powershell script from within powershell with arguments

I have spent the last 4 hours on this issue and would greatly appreciate any input you might have.
I need to call a powershell script with different credentials and pass arguments onto that script.
Following the installation of a program wrapped in WISEScript this script kicks off to gather AD accounts for the machine and remove them from specific AD Security Groups. Unfortunately as the script runs locally I cannot use ActiveDirectory modules in powershell as not all machines in our environment have RSAT.
The initial script is run from an elevated account on the machine:
$creds = New-Object System.Management.Automation.PsCredential("DOMAIN\USER", (ConvertTo-SecureString "Password" -AsPlainText -Force))
$ProfileGUIDS = Get-ChildItem 'hklm:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGuid'
$Groups = [ADSI]"LDAP://CN=Group4d_test,OU=GroupMigrationTesting,OU=TestOU,OU=US,DC=DOMAIN",[ADSI]"LDAP://CN=Group3d_test,OU=GroupMigrationTesting,OU=TestOU,OU=US,DC=DOMAIN"
Function Get-DistinguishedName ($strUserName)
{
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
$searcher.Filter = "(&(objectClass=User)(samAccountName=$strUserName))"
$result = $searcher.FindOne()
if ($result)
{
Return $result.GetDirectoryEntry().DistinguishedName
}
}
forEach ($GUIDkey in $ProfileGUIDS)
{
$GUID = Out-String -InputObject $GUIDKey
$index = $GUID.IndexOf("S-1")
$GUID = $GUID.Substring($index)
$GUID = $GUID.Substring(0,128)
$index = $GUID.IndexOf(" ")
$GUID = $GUID.Substring(0,$index)
$Profile = "hklm:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$GUID"
$ProfileItems = Get-ItemProperty $Profile
$SAM = $ProfileItems.ProfileImagePath
$index = $SAM.LastIndexOf("\")
$index ++
$SAM = $SAM.substring($index)
$UserDN = Get-DistinguishedName $SAM
$User = [ADSI]"LDAP://$UserDN"
if($User -ne $null)
{
forEach($group in $groups)
{
Right here is where I need to call the 2nd script with different credentials.
This is RemoveUsers.ps1, the script I need to run with different credentials:
param
(
[string]$group = "MyDefaultSAM",
[string]$user = "MyDefaultUser"
)
$Group.remove($User.ADsPath)
I have tried:
start-process powershell.exe -Credential $creds -NoNewWindow -ArgumentList "Start-Process $PSSCriptRoot\RemoveUsers.ps1 -Verb
This will run the script however I cannot specify any arguments
powershell.exe -file "$PSScriptRoot\RemoveUsers.ps1" -user $user -group $group
This calls the script with arguments but does not allow for the -Credentials switch
I have also tried:
$job = Start-Job -ScriptBlock {
powershell.exe -file "$PSScriptRoot\RemoveUsers.ps1" -user $user -group $group
} -Credential $creds
This runs but does not appear to work properly as the users remain in the AD groups.
Any help is appreciated.
Thanks - Jeff
**** UPDATE ****
Thanks for the information. When I add the changes you suggest I receive an error
Invoke-Command : Parameter set cannot be resolved using the specified named parameters
It appears, as I have found online, the -Credential switch cannot be used without the -Computer switch. If I specify $env:COMPUTERNAME or localhost for the computer I receive the error
\RemoveUsers.ps1 is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again
I can avoid this issue if I remove the -Credential switch and open the AD group to everyone. At this point I don't need to elevate a new powershell script and can add the command in the same. If I cannot resolve the issue with Invoke-Command this is likely what I will do.
**** UPDATE ****
What I ultimately had to do was use -Authentication Credssp in the argument list as there is an issue with using the AD Module via Invoke-Command. In addition I had to start the Win-RM service, Enable WSMacCredSSP (-role client on each machine and add a DelegateComputer entry and -role server on the server connecting to). Only after the service was started and an entry was made for WSManCredSSP was I able to use the Invoke-Command switch and have the AD Module work correctly.
This of course makes things more complicated and I decided just installing the AD Module on each PC (after finding a way to do it without RSAT) and forgetting about running the command remotely all together. Thanks for your help with the matter.
Thanks
You don't need to run PowerShell scripts with powershell.exe when calling them from another PowerShell script. Simply use the call operator (&). Also, I'd use Invoke-Command for running something inline with different credentials.
Beware that the scriptblock doesn't automatically know about the variables in the rest of your script. You need to pass them into the scriptblock via the -ArgumentList parameter. That is most likely the reason why removal didn't work when you ran RemoveUsers.ps1 as a job.
Something like this should work:
Invoke-Command -ScriptBlock {
& "$PSScriptRoot\RemoveUsers.ps1" -user $args[0] -group $args[1]
} -ArgumentList $user, $group -Credential $creds -Computer $env:COMPUTERNAME
This requires PSRemoting, though (run Enable-PSRemoting as an administrator).

MSBuild calling Powershell with credentials

I'm trying to deploy a windows service using an MSBuild script that runs a Powershell command.
The MSBuild script deploys the files I need and the PowerShell script will uninstall and reinstall the windows service using this command:
Invoke-Command -ComputerName IPAddressHere -FilePath "C:\theScriptFileName.ps1" -credential "TheUserName"
Using an IP address (which I need to because of different domains) I need to use credentials. The problem is that it prompts for a password, which won't work for TeamCity's automation.
I know I can save the credentials into a variable so that the prompt won't show, but I need to get it into a line something like the following that MSBuild can execute:
powershell.exe -NonInteractive -executionpolicy Unrestricted -command "& Invoke-Command -ComputerName IPAddressHere -FilePath 'C:\theScriptFileName.ps1' "
Is there a proper way to do this?
Use the code from Lee Holmes' article on exporting credentials:
function Export-Credential($cred, $path) {
$cred.Password = $cred.Password | ConvertFrom-SecureString
$cred | Export-Clixml $path
}
function Import-Credential($path) {
$cred = Import-Clixml $path
$cred.password = $cred.Password | ConvertTo-SecureString
New-Object System.Management.Automation.PSCredential($cred.username, $cred.password)
}
Save the credentials first in a regular session with the same user on the same machine that will be running the builds. (Well, on each such machine and user profile.) Then, in the build script, Import-Credential from the same path and pass the new $cred to Invoke-Command.
Maybe something like this?
$Creds = $host.ui.PromptForCredential("Need credentials", "Please enter username/password with proper rights on objects to manage.`r`n`r`nExample: AD-Domain\username", $env:userdomain + "\" + $env:username, "")
$IPAddressHere = "192.168.0.1"
powershell.exe -NonInteractive -executionpolicy Unrestricted -command "& {Invoke-Command -ComputerName $IPAddressHere -FilePath 'C:\theScriptFileName.ps1' -credentials $creds}"