Azure Devops Connect to SharePoint Online tenant - Connect-SPOService cmdlet timing out - powershell

Been working with using Azure DevOps to automate some PowerShell scripts against SharePoint Online. From what I understand, my first step needs to be getting authenticated against that tenant. So here's what I've got so far:
trigger:
- master
pool:
vmImage: 'windows-latest'
steps:
powershell: Install-Module -Name Microsoft.Online.SharePoint.PowerShell -RequiredVersion 16.0.8029.0 -force
displayName: 'Install SP Online PowerShell'
powershell: $cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $env:USERNAME, $(convertto-securestring $env:PASSWORD -asplaintext -force)
displayName: 'form the credentials var from previous vars'
powershell: Connect-SPOService -Url https://$env:ORG-admin.sharepoint.com -Credential $cred
displayName: 'connect to Tenant'
Environment variables username, password, and org are defined at the pipeline and seem to be working correctly (as in, I was getting different errors before deploying those). Now, I get to the final step and it just runs forever until I cancel it. It's as if it's getting some prompt on Connect-SPOService that, of course, I can't see, and so I can't respond to.
There are no errors to react to, just sits and spins and doesn't finish. My last error was that connect-sposervice wasn't a recognized cmdlet. To resolve that, I worked on my install-module command and got that resolved, so it seems like it's running that command properly now (no errors).
I can run all the same powershells from my local machine and get there without prompts or having to enter anything extra.
Anyone have any ideas?
Thanks!

It seems that you're following this document to connect to Sharepoint online.
Note: When prompted with the Windows PowerShell credential request dialog box, type the password for the SharePoint Online SharePoint administrator account.
When using Microsoft-hosted agent to run the PowerShell task, we can't access the UI to enter password in dislog box. So this is not supported way.
Instead, you may get help from these two documents: Installing the Office 365 CLI and Connecting to SharePoint Online.

Related

Access Denied on Powershell Start-Process within AzureDevOps task

I have an Azure DevOps task which needs to execute a Powershell script on a VM. The inline script generates a credential which is used as a parameter for the Powershell process being started.
- task: AzureCLI#2
inputs:
azureSubscription: 'MySubscription'
scriptType: 'ps'
scriptLocation: 'inlineScript'
inlineScript: |
az vm run-command invoke --command-id RunPowerShellScript --name $(MyVmName) -g My-RG --scripts `
"`$pw = ConvertTo-SecureString `"$(PasswordSecret)`" -AsPlainText -Force" `
"`$cred = New-Object System.Management.Automation.PSCredential 'Vm1\localadmin',`$pw" `
"Start-Process PowerShell -Cred `$cred -ArgumentList '-noexit','-File','C:\Users\localadmin\Documents\deploy.ps1'"
However, it appears that the Start-Process itself is getting Access Denied:
2021-04-21T22:15:29.6078202Z "message": "Start-Process : This command cannot be run due to the error: Access is denied.\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\1.1.8\\Downloads\\script11.ps1:3 char:1\n+ Start-Process PowerShell -Cred $cred -ArgumentList '-noexit','-File', ...\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n + CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException\n + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand"
The inline script below can be found on the vm and executed successfully using the same credentials that are used to generated the $cred. But, I'm guessing that since the DevOps task is running under a different, less privileged account, it doesn't have access to the Start-Process cmdlet.
Is there a way around this?
(Note: for several reasons beyond the scope of this post, I can't use the Powershell on Target Machines task, but I have in fact tried that.)
Are you running as a hosted agent? Are you using a deployment pool?
What I've tried is setting the local deployment agent service credentials on the machine- the service has a name like Azure Pipelines Agent. You can configure a Log On As account in the services pane and restart the service to enable the agent to run as that account.
This isn't a full answer but I can revisit and update based on your response and maybe we can figure out our problems together.
Edit: ** After a couple hours of labor I've unblocked myself by using .cmd instead of powershell. I discovered though that because the agents are running as services the .exe is not being launched unless in interactive mode. The deployment will continually 'run' while the .exe is running, otherwise. Instead of doing this, I decided to just reboot the computer using cmd and having the start up task run what I need.
Maybe your answer could be similar: place the script with the agent into the startup task, then reboot the computer and allow it to run it on it's own.

Powershell and Jenkins - Execute Powershell Script as another user

I have an environment formed by a Jenkins Server, a couple of Jenkins Slaves (windows) and several remote windows computers all part of the same domain.
I need to run a jenkins job, which executes a powershell snippet consisted of several functions (part of a custom modules loaded on the Jenkins Slave) against other windows remote computers in the same domain (which do not have the modules installed).
These modules needs to run under a specific domain account with permissions to access the remote computers.
If I logon with on any of the jenkins slave (with that specific domain account) everything works fine.
By default, Jenkins executes the job on the slave using the NT authority\system account which, of course, returns me denied access errors.
Question: is there a way to tell Jenkins to execute the Job on the windows slave with another specific Domain Account and not the NT Authority\System one?
Tried already:
Invoke-command using credentials: this is not an option since the remote computers do not have the modules
Impersonation: tried a couple of functions found on the PS gallery but do not work
You can run powershell as a process in a script and call that from Jenkins. In the script also you can use like:
$username = 'username'
$password = 'password'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username,$securePassword
Start-Process Powershell.exe -Credential $credential
Hope it helps.

Trying to Log in to Azure in Powershell

I am following the MS guide located here and everything goes through correctly until I have to actually log in. The pop up window appears for my creds and validates them, but powershell doesn't seem to notice.
So it goes Install Module, Import Module, Verify Version, Log in. See below for what happens on the last two steps.
PS C:\WINDOWS\system32> Get-Module AzureRM -ListAvailable | Select-Object -Property Name,Version,Path
Name Version Path
---- ------- ----
AzureRM 6.3.0 C:\Program Files\WindowsPowerShell\Modules\AzureRM\6.3.0\AzureRM.psd1
PS C:\WINDOWS\system32> Connect-AzureRmAccount
Account :
SubscriptionName :
SubscriptionId :
TenantId :
Environment :
PS C:\WINDOWS\system32>
Of course, this prevents me from doing very much else with Azure from that point forward.
Edit: Issue appears on multiple workstations
I got this same issue. I have two users like many of you: the Azure user that is the "Work" account, and then the "Personal" account which is also created automatically by Office365 and Azure. I was getting the issue when I tried to use my "personal" account, in which I have some subscriptions added (delegated).
After trying lots, what worked for me was to login to the "Work" account when the "Connect-AzureRmAccount" command asks for an username/password. Then, I again use the command "Connect-AzureRMAccount", but this time I entered the personal account, and it finally worked.
Picture here
Edit: A better way I found later was this, as I manage a lot of subscriptions/tenants from a single account (delegated access):
Put the “tenantid” into a variable (you can get this ID on the Azure Portal, in my case, on the option to change directories):
How to get your tenant's IDs quickly
$tenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Login specifying the TenantId:
Login-AzureRmAccount -TenantId $tenantId
Example 2
This behavior happens when you run
Clear-AzureRMContext -Scope CurrentUser
I'm not sure why and im attempting to debug on how to fix the issue. A work around is to close the powershell window and reopen a new powershell windows that does not have this command ran.
Running the command
Enable-AzureRmContextAutosave -Scope CurrentUser
Fixed the issue for me. This will autosave your context for every powershell session. If this is not desired you can run the command
Enable-AzureRmContextAutosave -Scope Process
which will save the azure context for only the process. Otherwise you will need to handle
You can try this...
Install-Module PoweshellGet -Force
Set-ExecutionPolicy -ExicutionPolicy Remotesigned
Install-Module AzureRm
Import-Module -Name AzureRm
Login-AzureRmAccount
You can use the below link to install latest PowerShell version:
https://github.com/Azure/azure-powershell/releases
And then use something like this in order to automatically pass in the username password, and skipping the UI:
$azureAccountName ="enter username here"
$azurePassword = ConvertTo-SecureString "password here" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAccountName, $azurePassword)
Login-AzureRmAccount -Credential $psCred
Have you tried the following:
Import-Module Microsoft.Powershell.Security
$azureAccountName ="enter username here"
$azurePassword = ConvertTo-SecureString "password here" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAccountName, $azurePassword)
$decrypt = $psCred.GetNetworkCredential()
$ptpass = $decrypt.Password
Write-Output "Logging in to Azure using $azureAccountName with a password of $ptpass"
Login-AzureRmAccount -Credential $psCred
If you receive an error with this code, please comment with the entire error message.
The only thing i can think of is the below
You maybe using Azure Service Management (Azure V1 / Azure Classic) which uses a different module to Azure Resource Manager (ARM , Azure V2).
To install Azure Service Management Module:
Install-Module Azure -AllowClobber
Allowing clobber because you already have AzureRM Module installed
Import Azure Module to PowerShell:
Import-Module Azure
Logs into ASM:
Add-AzureAccount
Shows you all subscriptions
Get-AzureSubscriptions
Selects the Subscription you allocate to work within
Select-AzureSubscription
Answered something similar in the below Thread:
Login-AzureRmAccount return subscription but Get-AzureSubscription return empty
Hope this helps
You can try logging in using the Service Principal credentials.
Service principal is an application created under Active Directory to which you can apply permission rules.
$pscredential = Get-Credential
Connect-AzureRmAccount -ServicePrincipal -ApplicationId "http://my-app" -Credential $pscredential -TenantId $tenantid
Refer here for more details.

Using AzureAD PowerShell CmdLets on TFS Release Manager

I want to execute some PowerShell scripts on our TFS Release Manager environment that use AzureAD module to provision some Azure AD groups. The scripts are executed using an Azure Powershell Task. I've installed the AzureAD module, so the AzureAD PowerShell CmdLets are recognized.
However, for them to work the scripts first needs to connect to AzureAD using the Connect-AzureAD CmdLet. This CmdLet wants to show a modal dialog for entering credentials, which obviously isn't possible in a Release Manager task. I also cannot supply credentials using command line parameters. I want Connect-AzureAD to somehow use the current user context for the connection. Is this possible?
You could use the -Credential option of Connect-AzureAD.
In your AzureAD task, you can use the following code:
```
$pass=ConvertTo-SecureString $Env:password -AsPlainText -Force
$credential=New-Object PSCredential($Env:login, $pass)
Connect-AzureAD -Credential $credential
```
login and password are stored in a secret variable in the release definition.
Alternatively you might get the password from a previous task in the build definition. I that case, in the script arguments of the task, you pass the password -password "$(password)"
and in the `Script or Script inline you have, this time:
``
param([string]$password)
$pass=ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object PSCredential($Env:login, $pass)
Connect-AzureAD -Credential $credential
``
I get the password from KeyVault with the Azure KeyVault task, but that might not be an option for you if you are on premise.
We've found an answer. It had been setting right in front of us on the official Connect-AzureAD documentation page (example 3).
So we're now authenticating using a SPN and a self-signed certificate. This works just fine.

How to delete a folder on an Azure App Service website using Octopus Deploy

I am setting up an automated deployment project for a Sitecore website using TeamCity and Octopus Deploy (v. 3.3.6).
Before deploying to the App Service using a "Deploy an Azure Web App" step, I would like to delete one folder on that site (/site/wwwroot/App_Config/Include or D:\home\site\wwwroot\App_Config\Include).
Is there a built-in mechanism in Octopus to do this? I have tried using a Powershell script, but that runs on the server, not on Azure. Is there a way to run a Powershell script on Azure while deploying?
Or can I use the "Run an Azure Powershell Script" to do file manipulations on an App Service website without having to authenticate (since Octopus is doing the authentication)?
Or are there any other/better solutions to solve this without having to save credentials in a file on the Build Server?
I would prefer not to use FTP for this, if at all possible.
I would do this:
Create a on-demand webjob in Azure and upload a powershell script that can clean up the folder to your Webapp. Try to keep this ps script simple, use base cmdlet commands, not all ps modules would run in azure.
How: https://blogs.msdn.microsoft.com/nicktrog/2014/01/22/running-powershell-web-jobs-on-azure-websites/
You still need your teamcity or octopus to run a powershell line to kick off the webjob. With that, the work load is not on octopus server anymore but you still need the same azure authentication process for the powershell line.
How: http://www.nullfactory.net/2015/05/start-azure-webjobs-on-demand/
"Run an Azure Powershell Script" in octopus helps you load the Azure Powershell module and do the Azure-Subscription trick, so you don't need to include the library within the script or re-authenticate. It still runs locally but step #2 fits this well.
Hope this can help you.
In the end I decided to use FTP anyway. Even though I quite like Kai Zhao's suggestion, I preferred to keep all things related to the automated deploy on the deploy server instead of having to put and maintain scripts in different locations.
I used the following Powershell FTP Client Module and installed it on our build server: https://gallery.technet.microsoft.com/scriptcenter/PowerShell-FTP-Client-db6fe0cb
And I used this script to do the actual delete and run it as a step in Octopus:
$AzureAppService is a variable in Octopus which changes depending on the
environment.
Import-Module PSFTP
$username = $AzureAppService
$password = ConvertTo-SecureString "************" -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential `
-argumentlist $username, $password
$ftpserver = "***url_to_your_ftp_server**"
$folderToDelete = "/site/wwwroot/App_Config/Include"
Set-FTPConnection -Credentials $cred -Server $ftpserver -Session MyFTPSession -UsePassive
$Session = Get-FTPConnection -Session MyFTPSession
Try
{
Remove-FTPItem -Session $Session -Path $folderToDelete -Recurse
}
Catch
{
Write-Warning "There was an error while trying to remove the folder:"
Write-Warning $_.Exception.Message
Write-Warning $_.Exception.ItemName
}