How to specify application pool identity user and password from PowerShell - iis

I have been having lots of difficulty automating the setup of a Web application and configuring IIS appropriately with the Application Pool Identity. I am doing this in a Web application deployment script written in PowerShell. My requirement is that I need my PowerShell script to set the application pool identity user to a specific service account mydomain\svcuser and password. Here is the sample code:
$pool = New-Item "IIS:\AppPools\MyAppPool" -Force
$svcuser = "mydomain\svcuser"
$pool.processModel.userName = $svcuser
$password = "somepassword"
$pool.processModel.password = $password
$pool.processModel.identityType = 3
$pool | Set-Item -ErrorAction Stop
When I run this, everything appears to work correctly--no errors are thrown and the application identity user name appears in IIS--but for some reason the password does not get set correctly, if at all. Since it is a password I cannot verify whether it has been set, but I can conclude that it if it is, it is not set correctly. It will not authenticate the resulting application pool user until I manually go in and enter the password in IIS. As a result the application fails after being deployed to the Web server and requires manual intervention.
Am I missing something here?

You would do this as follows:
Import-Module WebAdministration
Set-ItemProperty IIS:\AppPools\app-pool-name -name processModel -value #{userName="user_name";password="password";identitytype=3}
See this document here for an explanation, and a reference of the indentity type numeric for the user type you will run the app pool under: http://www.iis.net/configreference/system.applicationhost/applicationpools/add/processmodel

After few experiments
Here is my Answer, I hope this will helps , I've worked on IIS 8.5
$credentials = (Get-Credential -Message "Please enter the Login credentials including Domain Name").GetNetworkCredential()
$userName = $credentials.Domain + '\' + $credentials.UserName
Set-ItemProperty IIS:\AppPools\$app_pool_name -name processModel.identityType -Value SpecificUser
Set-ItemProperty IIS:\AppPools\$app_pool_name -name processModel.userName -Value $username
Set-ItemProperty IIS:\AppPools\$app_pool_name -name processModel.password -Value $credentials.Password

seems you can do this a little more directly now
appcmd set apppool junkapp /processmodel.password:junkpassword

I'm on powershell v4 which doesn't have 'ConvertFrom-SecureString', in the end I got the following to work for me:
Import-Module WebAdministration
$cred = Get-Credential -Message "Please enter username and new password to reset IIS app pool password (for app pools running as username)"
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($cred.Password)
$plaintext = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
$applicationPools = Get-ChildItem IIS:\AppPools | where { $_.processModel.userName -eq
$cred.UserName }
foreach($pool in $applicationPools)
{
$apppool = "IIS:\AppPools\" + $pool.Name
Set-ItemProperty $apppool -name processModel.password -Value $plaintext
}
Write-Host "Application pool passwords updated..." -ForegroundColor Magenta
Write-Host ""
Read-Host -Prompt "Press Enter to exit"

Related

How to change IIS app pool password on multiple servers at once remotely?

We have a requirement to change our application's IIS app pool password everytime it expires. Currently, we have to manually login to each server and run a snippet of PowerShell code which changes the password.
Here is the code we run on each server on PS:
Import-Module WebAdministration
$applicationPools = Get-ChildItem IIS:AppPools | where { $_.processModel.userName -eq "Domain\XXXXX12345" }
foreach($pool in $applicationPools)
{
$pool.processModel.userName = "Doma\XXXXX12345"
$pool.processModel.password = "XXXXXXXXXXXXXXXXX"
$pool | Set-Item
}
Write-Host "Application pool passwords updated..." -ForegroundColor Magenta
Write-Host ""
Read-Host -Prompt "Press Enter to exit"
But is there a way we can do the same for a list of servers/VMs at once instead of having to login to each server, open PowerShell or IIS and manually change it on each server?
Any help would be greatly appreciated!
You could try to create an Azure DSC Configuration for this. This way you could provide a new configuration state every time the password expires.
https://learn.microsoft.com/en-us/azure/automation/quickstarts/dsc-configuration
https://writeabout.net/2015/04/15/use-the-dsc-script-resource-to-change-the-application-pool-identity/
could you try this below script:
$computerName = 'MyServerName'
$appPoolName = 'DefaultAppPool'
Invoke-Command -ComputerName $computerName -args $appPoolName -ScriptBlock {
param($appPoolName)
$appPoolName.Stop()
$appPoolName | Set-ItemProperty -Name "processModel.username" -Value "Doma\XXXXX12345"
$appPoolName | Set-ItemProperty -Name "processModel.password" -Value "XXXXXXXXXXXXXXXXX"
$targetpool.Start()
}
Write-Host "Application pool passwords updated..."

Azure Automation Job runs fine manually but fails when triggered by webhook

I've got an Automation Account in Azure that runs a Powershell runbook.
It runs perfectly fine when I trigger it via the portal, manually specifying the inputs
I've created a webhook with the same input settings. I call it from CURL like
curl -d '' https://800b2bec-b1ae-4fa1-ba30-8c7d32096828.webhook.ae.azure-automation.net/webhooks?[redactedtoken]
The webhook shows as triggered successfully in the portal, however the job fails with no visible error.
There is no output, even though the first line in my powershell function is Write-Output "Hello"
There are no exception messages, no logs at all.
Any idea how I might get more information as to what might be going wrong?
I've updated the Az modules and enabled verbose logging in the runbook.
Full source below, if it helps.
Param(
[string]$resourceGroup,
[string]$VMName,
[string]$method,
[string]$UAMI
)
Write-Output "Hello"
$automationAccount = "AlsAutomation"
# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process | Out-Null
# Connect using a Managed Service Identity
try {
$AzureContext = (Connect-AzAccount -Identity).context
}
catch{
Write-Output "There is no system-assigned user identity. Aborting.";
exit
}
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
-DefaultProfile $AzureContext
if ($method -eq "SA")
{
Write-Output "Using system-assigned managed identity"
}
elseif ($method -eq "UA")
{
Write-Output "Using user-assigned managed identity"
# Connects using the Managed Service Identity of the named user-assigned managed identity
$identity = Get-AzUserAssignedIdentity -ResourceGroupName $resourceGroup `
-Name $UAMI -DefaultProfile $AzureContext
# validates assignment only, not perms
if ((Get-AzAutomationAccount -ResourceGroupName $resourceGroup `
-Name $automationAccount `
-DefaultProfile $AzureContext).Identity.UserAssignedIdentities.Values.PrincipalId.Contains($identity.PrincipalId))
{
$AzureContext = (Connect-AzAccount -Identity -AccountId $identity.ClientId).context
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
}
else {
Write-Output "Invalid or unassigned user-assigned managed identity"
exit
}
}
else {
Write-Output "Invalid method. Choose UA or SA."
exit
}
# Get current state of VM
$status = (Get-AzVM -ResourceGroupName $resourceGroup -Name $VMName `
-Status -DefaultProfile $AzureContext).Statuses[1].Code
Write-Output "`r`n Beginning VM status: $status `r`n"
# Start or stop VM based on current state
if($status -eq "Powerstate/deallocated")
{
Start-AzVM -Name $VMName -ResourceGroupName $resourceGroup -DefaultProfile $AzureContext
}
elseif ($status -eq "Powerstate/running")
{
Stop-AzVM -Name $VMName -ResourceGroupName $resourceGroup -DefaultProfile $AzureContext -Force
}
# Get new state of VM
$status = (Get-AzVM -ResourceGroupName $resourceGroup -Name $VMName -Status `
-DefaultProfile $AzureContext).Statuses[1].Code
Write-Output "`r`n Ending VM status: $status `r`n `r`n"
Write-Output "Account ID of current context: " $AzureContext.Account.Id
We have tested this in our local environment it is working fine, Below statements are based on the analysis.
In our local environment, We have created a Powershell runbook running with different PowerShell Versions 7.1 & Version 5.1.
Using the above share Script & webhook URI, when we are trying to invoke the runbook (PowerShell version 7.1) using the `Invoke-webRequest method it is continuously failing.
Alternatively, We have tried to invoke the runbook (PowerShell version 5.1) using the Invoke-webRequest method it is working fine.
We would suggest you to use Powershell Version 5.1 instead of 7.1 in your Runbook.
Here is the sample Output for reference:

Runbook Run Powershell as azure acccount

I got a script on a VM within the subscription/rg that runs a ps module called Qlik-Cli, it uses a certificate and a login.
The certificate is stored in the local store for the serviceaccount, not a choise, how the product works.
I need to trigger this thorgh a powershell runbook.
In order for this to work, I need to trigger this with the service account, cause it won't find the certificate otherwise.
This is something we are going to schedule so it has to be done this way.
How can I run it this way, or is it not possible?
I can't find any good option when googeling it.
> Import-Module -Name Qlik-Cli
> [Net.ServicePointManager]::SecurityProtocol =
> [Net.SecurityProtocolType]::Tls12 $logpath =
> "E:\Tools\Scripts\log.txt" get-childitem cert:\currentuser\My\ |
> where {$_.Thumbprint -eq '"thumbprint"'} |
> Connect-Qlik "DNS" -UserName
> "user" -TrustAllCerts -verbose 4>&1 | Out-File
> -Append $logpath Start-QlikTask -id df9dfa2f-32ca-4db4-bdce-15ad924fd59f -verbose 4>&1 | Out-File -Append
> $logpath
The script in the runbook:
$ServicePrincipalConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
Add-AzAccount -ServicePrincipal -TenantId $ServicePrincipalConnection.TenantId -ApplicationId $ServicePrincipalConnection.ApplicationId -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint
$rgname ="Resource-Group"
$vmname ="Virtual machine name"
$ScriptToRun = "E:\Tools\Scripts\Tasktrigger.ps1"
Out-File -InputObject $ScriptToRun -FilePath ScriptToRun.ps1
Invoke-AzVMRunCommand -ResourceGroupName $rgname -Name $vmname -CommandId 'RunPowerShellScript' -ScriptPath ScriptToRun.ps1
Remove-Item -Path ScriptToRun.ps1
What the logs says from the script (local script) when I execute the runbook is that it can't find the certificate which is not strange.
Raw output:
Found 0 certificates in the current user store
Found 0 certificates in the local machine store
No valid certificate found, using windows credentials
Used the code on Github for the module Click-Cli to backtrack the error message. Had to change certificate and imporrt the new one in personal / machine store.
Also the default username when running it from outside the QlikServer is domain\Servername$, which means you have to change permissions on the account in QlikSense to allow it to execute tasks.
You can see the name if you use verbose logging to file once you added the right certficate all the way.
The Qlik-CLI module, reads the client, QlikClient, certificate from cert:\\CurrentUser\My.
So, if you are trying to run Qlik-CLI scripts as a different user than the Qlik Sense service user account (or on another machine), you need to log in as the service account, export the QlikClient certificate, including the private key, and install it under the user running the script.
The -UserName argument is just to tell Qlik who you want to be, given that you have the certificate in order.
To cut it short: Run the script as the Qlik service user. It will save you a lot of hassle. :)

Access Azure App Service files from Azure CLI

I would like to move a file within an Azure App Service from a script. I thought that Azure CLI with az webapp command could be used for that, but could not find a way to access the files.
I know that there is Kudu REST API for file access, but I want to run the script during an Azure Devops Pipeline, so authentication for the REST API seems like an issue - I don't want to store the credentials in the pipeline. The same holds for FTP access.
However, there is an Azure CLI task with authorization through configured Service connections, so I thought this might be the way.
So, the core question is - How to move a file within Azure App Service from a command line?
So, it turned out that I can use Azure CLI to get Publishing profile for a particular App service (or even slot) and then use the user name and password from it to access Kudu REST API.
I used this Powershell 6 script
function Get-PublishingProfile($resourceGroupName, $webAppName, $slotName) {
if ([string]::IsNullOrWhiteSpace($slotName)) {
$xml = Get-AzWebAppPublishingProfile -ResourceGroupName $resourceGroupName -Name $webAppName
}
else {
$xml = Get-AzWebAppSlotPublishingProfile -ResourceGroupName $resourceGroupName -Name $webAppName -Slot $slotName
}
return $xml |
Select-Xml -XPath "publishData/publishProfile[1]" |
Select-Object -ExpandProperty Node |
Select-Object -Property publishUrl, msdeploySite, userName, userPWD, destinationAppUrl
}
$profile = Get-PublishingProfile $resourceGroupName $webAppName $slotName
$securePassword = ConvertTo-SecureString -String $profile.userPWD -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($profile.userName, $securePassword)
$fileUri = "https://$($profile.publishUrl)/api/vfs/site/wwwroot/some_file.txt"
$headers = #{
"If-Match" = "*"
}
Invoke-RestMethod -Uri $fileUri -Method Get -Credential $credentials -Authentication Basic -Headers $headers

Create IIS website on remote server using PowerShell

I'm trying to create IIS website on a remote server from another server using powershell. When I execute it, the site has created in local server, not in the remote server.
This is the powershell function. It is in function.ps1 file.
function CreateIISWebsite
{
param (
[string]$iisAppName,
[string]$directoryPath,
[string]$iisAppPoolName,
[string]$rhost,
[string]$un,
[string]$pw
)
$MSDeployExe = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe"
Import-Module WebAdministration
$iisAppPoolDotNetVersion = "v4.0"
#navigate to the app pools root
cd IIS:\AppPools\
#check if the app pool exists
if (Test-Path $iisAppPoolName -pathType container)
{
Remove-Item $iisAppPoolName -recurse
}
#create the app pool
$appPool = New-Item $iisAppPoolName
$appPool | Set-ItemProperty -Name "managedRuntimeVersion" -Value $iisAppPoolDotNetVersion
Set-ItemProperty IIS:\AppPools\$iisAppPoolName managedRuntimeVersion v4.0
Set-ItemProperty -Path IIS:\AppPools\$iisAppPoolName -Name processmodel.identityType -Value 3
Set-ItemProperty -Path IIS:\AppPools\$iisAppPoolName -Name processmodel.username -Value $un
Set-ItemProperty -Path IIS:\AppPools\$iisAppPoolName -Name processmodel.password -Value $pw
#navigate to the sites root
cd IIS:\Sites\
#check if the site exists
if (Test-Path $iisAppName -pathType container)
{
Remove-Item $iisAppName -recurse
}
#create the site
$iisApp = New-Item $iisAppName -bindings #{protocol="http";bindingInformation=":80:" + $iisAppName} -physicalPath $directoryPath
$iisApp | Set-ItemProperty -Name "applicationPool" -Value $iisAppPoolName
}
I call this function like this.
. ./function.ps1
CreateIISWebsite -iisAppName $sitename -directoryPath $path -iisAppPoolName $appPool -rhost $rhost -un $un -pw $pw
Even though i pass ip of the remote server as rhost i have no idea where i need to use it. So IIS site is creating in local successfully. Without using rhost parameter it won't create in server. So I need to use that parameter in correct place in the code.
I have installed Web Deploy in both servers.
Please suggest me a solution.
Configure PowerShell Remoting on the local and remote systems (use Enable-PSRemoting -Force, and then deploy the script to the remote computer by using Invoke-Command.
UPDATE
e.g.
On your local and remote systems write this in an elevated Powershell Command Prompt:
Enable-PSRemoting -Force
Remember also to Set-ExecutionPolicy (See here for more info) to something appropriate on the remote server if you have not already done so.
To invoke the powershell script on the remote machine from your local machine you can then do something like this:
Invoke-Command -ComputerName server01 -File c:\path\to\script.ps1

Resources