Can't change DSC LCM credential - powershell

When attempting to access a network shared folder, DSC returns an "Access is denied" error, despite that I have provided a valid credential to it.
I'm using a DSC configuration, where a DSC "Script" resource is as follows:
Script myScriptResource {
GetScript = {return $true}
SetScript = {
$setupShare = '\\SomeNetworkSharesFolder\subFolder'
# This line produces valid results when run directly on node VM.
$build = Get-ChildItem "FileSystem::$setupShare" -Name | Sort-Object -Descending | Select-Object -First 1 | Out-String
Write-Host "Final Build: $build"
}
TestScript = {return $false} #Always run Set-Script block!
Credential = $ValidNetworkShareCredential
PsDscRunAsCredential = $ValidNetworkShareCredential
}
I receive an error:
VERBOSE: [MyNodeVM]: [[Script]myScriptResource] Performing the operation "Set-TargetResource" on target "Executing t
he SetScript with the user supplied credential".
Access is denied
+ CategoryInfo : PermissionDenied: (\\SomeNetworkSharesFolder\subFolder:) [], CimException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
+ PSComputerName : myNodeVM
This might be due to the fact the LCM on the node VM is using a local SYSTEM user credential by default.
I attempted to change the user credential manually by navigating to the windows services manager (Hint: RUN then services.msc), and change the user credential in the logon tab of winRM service properties. Everytime I attempt to run the Windows Remote Management (WS-Managment) service, I receive and error:
Windows could not start the Windows Remote Management (WS-Management) service on Local Computer.
Error 1079: The account specified for this service is different from the account specified for other services running in the same process.
I don't know how to change the credential of LCM so that it can access the network shared folder upon the execution of Get-ChildItem.

Script myScriptResource {
GetScript = {return $true}
SetScript = {
$username ="someusername"
$secpasswd = ConvertTo-SecureString “somepassword” -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
$setupShare = '\\SomeNetworkSharesFolder\subFolder'
$psDriveArgs = #{ Name = ([guid]::NewGuid()); PSProvider = "FileSystem"; Root = $setupShare; Scope = "Private"; Credential = $mycreds }
new-psdrive #psDriveArgs -ErrorAction Stop
# This line produces valid results when run directly on node VM.
$build = Get-ChildItem "FileSystem::$setupShare" | Sort-Object -Descending | Select-Object -First 1 | Out-String
Write-Host "Final Build: $build"
}
TestScript = {return $false} #Always run Set-Script block!
}

There isn't an easy way to make it work with script resource because you need an ability to pass credentials to the script resource so that you can mount a drive and use it to copy/paste. If you want to copy files/directory from the share you can use 'File' resource. If you want to copy files/directory to the share you can use 'xFileUpload' resource from xPsDesiredStateConfiguration (https://gallery.technet.microsoft.com/xPSDesiredStateConfiguratio-417dc71d) Module. If you really need to use script resource to do this job, look into how xFileUpload resource is doing it.

Related

Azure Function app won't load dependencies

I have checked the requirements.psd1 several times and it all appears right, but the function returns this error when running.
[Warning] The Function app may be missing a module containing the 'Set-AzStorageBlobContent' command definition. If this command belongs to a module available on the PowerShell Gallery, add a reference to this module to requirements.psd1. Make sure this module is compatible with PowerShell 7. For more details, see https://aka.ms/functions-powershell-managed-dependency. If the module is installed but you are still getting this error, try to import the module explicitly by invoking Import-Module just before the command that produces the error: this will not fix the issue but will expose the root cause.
2022-09-13T22:12:00.401 [Error] ERROR: The term 'Set-AzStorageBlobContent' 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.Exception :Type : System.Management.Automation.CommandNotFoundExceptionErrorRecord :Exception :Type : System.Management.Automation.ParentContainsErrorRecordExceptionMessage : The term 'Set-AzStorageBlobContent' 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.HResult : -2146233087TargetObject : Set-AzStorageBlobContentCategoryInfo : ObjectNotFound: (Set-AzStorageBlobContent:String)
I am not sure what i'm missing. I've read through other fixes i've found and believe I have it configured correctly. It feels "buggy". Here's my config below:
function.json
{
"bindings": [
{
"name": "Timer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 * * * * *"
}
]
}
host.json
{
"version": "2.0",
"managedDependency": {
"Enabled": true
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[2.*, 3.0.0)"
}
}
profile.ps1
#if ($env:MSI_SECRET) {
# Disable-AzContextAutosave -Scope Process | Out-Null
# Connect-AzAccount -Identity
#}
requirements.psd1
# This file enables modules to be automatically managed by the Functions service.
# See https://aka.ms/functionsmanageddependency for additional information.
#
#{
# For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'.
# To use the Az module in your function app, please uncomment the line below.
'Az' = '7.*'
'Az.KeyVault' = '4.*'
'Az.Storage' = '4.*'
}
and the script that's running
#---------------------------------------------------------[Variables]------------------------------------------------------------
$storageAccountName = 'storageaccount'
$containerName = '$web'
$logContainerName = 'logfiles'
$subscription = 'Subscription'
$resourceGroupName = 'resourcegroup'
$blob = 'info.txt'
$logBlob = 'info.log'
$uri = "https://api.binaryedge.io/v1/minions"
#----------------------------------------------------------[Execution]-------------------------------------------------------------
# Call the API to get the IP addresses
Try {
$call = Invoke-RestMethod $uri -ErrorAction Stop
$list = $call.scanners
# New-TemporaryFile uses [System.IO.Path]::GetTempPath() location
$tempFile = New-TemporaryFile
# Set the context to the subscription you want to use
# If your functionApp has access to more than one subscription it will load the first subscription by default.
Set-AzContext -Subscription $subscription
# Get the Storage Account Key to authenticate
$storAccKeys = Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName
$primaryKey = $storAccKeys | Where-Object keyname -eq 'key1' | Select-Object -ExpandProperty value
# Write the CIDR list to the temp file created earlier
$list | Out-File $tempFile
# Create a Storage Context which will be used in the subsequent commands
$storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $primaryKey
# Upload the temp file to blob storage
$setAzStorageBlobContentSplat = #{
Container = $containerName
File = $tempFile.FullName
Blob = $blob
Context = $storageContext
Properties = #{
ContentType = 'text/plain'
}
}
Set-AzStorageBlobContent #setAzStorageBlobContentSplat -Force
Write-Host Success!
}
Catch {
Out-Host $_.exception.message
}
Finally {
$time = Get-Date
$tempFile = New-TemporaryFile
"Script last completed at $time" | Out-File $tempFile -Append
$setAzStorageBlobContentSplat = #{
Container = $logContainerName
File = $tempFile.FullName
Blob = $logBlob
Context = $storageContext
Properties = #{
ContentType = 'text/plain'
}
}
Set-AzStorageBlobContent #setAzStorageBlobContentSplat -Force
}
Figured it out. For whatever reason, Connect-AzAccount is now required. Since I used a managed identity, the command to allow the script to run is Connect-AzAccount -Identity. You also need to add Az.Accounts to the requirements.psd1. This was the fix.
In the profile.ps1 file, I also had to uncomment the lines. This is the default, but I did it to get rid of one of the errors.
I will state for the record...several months ago this was NOT a requirement to make a script run. It also wasn't working in the profiles.ps1 file prior to commenting it out either.
I would recommend following the suggestion in the warning message and invoking Import-Module Az.Storage just before Set-AzStorageBlobContent. This will probably not fix the issue, but Import-Module will tell you why it cannot load the module.

Cannot set credentials with New-Service; have to use sc.exe config – why?

I'm working on a PowerShell script that's …
creating a local user
adding that user to the "Log-in as Service" policy
creating a new service that's supposed to run as the user that's been created in the previous step
When the script first creates the service using New-Service with default credentials and then changes the service's credentials using 'sc.exe', everything runs fine.
But when I try to provide the same credentials right in the call to New-Service, that call fails with exception: "Cannot create service. Reason: Improper user name or password."
What am I doing wrong?
Here's the existing code that's working
New-Service -Name $service.ServiceName -DisplayName $service.DisplayName -BinaryPathName "$binaryFolder" -StartupType Manual > $null
$scOutputText = & sc.exe config $service.ServiceName obj=".\$($userAccount.Username)" password="$($userAccount.Password)" | Out-String
Here's my code that's not working
$params = #{
Name = $service.ServiceName
DisplayName = $service.DisplayName
BinaryPathName = "$binaryFolder"
StartupType = 'Manual'
Credential = (New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList $userAccount.Username, (ConvertTo-SecureString $userAccount.Password -AsPlainText -Force))
}
New-Service #params

Create azure dynamic group from azure functions powershell

I am trying to create an azure function that has to create azure dynamic group when i execute the function from MS flow. I am using below code for this purpose.
$groupName = $Request.Query.Name
$groupDesc = $Request.Query.Desc
$domainnames = $Request.Query.DomainName
$dynamicrule = ""
Foreach($domainname in $domainnames.Split(";"))
{
$dynamicrule = $dynamicrule + "(user.userPrincipalName -contains ""_$domainname"") or";
}
$dynamicrule = $dynamicrule -replace ".{2}$"
$dynamicrule = $dynamicrule + "and (user.objectId -ne null)";
New-AzureADMSGroup -DisplayName $groupName -Description $groupDesc -MailEnabled $False -MailNickName "group" -SecurityEnabled $True -GroupTypes "DynamicMembership" -MembershipRule $dynamicrule -MembershipRuleProcessingState "On"
When i execute the above command, i am getting below error messgae.
ERROR: The term 'New-AzureADMSGroup' 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.Exception :Type : System.Management.Automation.CommandNotFoundExceptionErrorRecord
Can sombody please help me on how can i create dynamic groups using azure function app.
Thanks,
Venu
From the error message, you did not install AzureAD powershell module in your function app. And if you want to create a dynamic group, you need to use the -MembershipRule parameter, it is just available in the preview version i.e. AzureADPreview module. Though the doc looks like the parameter is available in AzureAD, but per my test, it is not available.
Actually it is easy to solve the issue, but if you want to create a dynamic group with New-AzureADMSGroup, there will be a few follow-up issues, you could follow the steps below.
1.Navigate to the function app in the portal -> Identity -> enable the system-assigned identity(MSI) for your app.
2.Navigate to App files -> host.json -> make sure the managedDependency is Enabled.
{
"version": "2.0",
"managedDependency": {
"Enabled": true
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
In the requirements.psd1, add the AzureADPreview like below, then it will install the AzureADPreview module for you automatically.
#{
'Az' = '5.*'
'AzureADPreview' = '2.0.2.129'
}
In the profile.ps1, remove all the things and add the lines below, this is used to solve the issue related to AzureAD powershell in function, without it, you will get an error, details here.
$64bitPowerShellPath = Get-ChildItem -Path $Env:Windir\WinSxS -Filter PowerShell.exe -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.FullName -match "amd64"}
$env:64bitPowerShellPath=$64bitPowerShellPath.VersionInfo.FileName
3.If you want to use New-AzureADMSGroup to create group in Azure AD, you need the permission in Microsoft Graph, in this case, we use MSI to auth, so use the commands below to give the permission to your MSI.
Run the commands below in local with the Global admin user account, replace <functionapp-name>:
Connect-AzureAD
$MSI = (Get-AzureADServicePrincipal -Filter "displayName eq '<functionapp-name>'")
$MSGraphAppId = "00000003-0000-0000-c000-000000000000"
$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$MSGraphAppId'"
$PermissionName = "Group.ReadWrite.All"
$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"}
New-AzureADServiceAppRoleAssignment -ObjectId $MSI.ObjectId -PrincipalId $MSI.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id
4.After step 2, navigate to the kudu(in the Advanced Tools blade of the function app) -> data -> ManagedDependencies -> click the file with the format like 201208083153165.r(choose the newest one via the Modified time) -> check if the AzureADPreview module was installed successfully like below.
5.After the module was installed, in your function code, use the lines below, in my sample, I use this sample to test directly, you could change the code depends on your requirements, remember to replace 201208083153165.r with yours in step 4, it works fine on my side.
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with query parameters or the body of the request.
$name = $Request.Query.Name
if (-not $name) {
$name = $Request.Body.Name
}
$body = "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
if ($name) {
$body = "Hello, $name. This HTTP triggered function executed successfully."
}
$script = {
if ($env:MSI_SECRET) {
Disable-AzContextAutosave -Scope Process | Out-Null
Connect-AzAccount -Identity
}
$context = Get-AzContext
$graphtoken = (Get-AzAccessToken -ResourceUrl "https://graph.microsoft.com").Token
$aadtoken = (Get-AzAccessToken -ResourceUrl "https://graph.windows.net").Token
Import-Module D:\home\data\ManagedDependencies\201208083153165.r\AzureADPreview
Connect-AzureAD -AccountId $context.Account -TenantId $context.Tenant -MsAccessToken $graphtoken -AadAccessToken $aadtoken
New-AzureADMSGroup -DisplayName "joyd1" -Description "Dynamic group created from PS" -MailEnabled $False -MailNickName "group" -SecurityEnabled $True -GroupTypes "DynamicMembership" -MembershipRule "(user.department -contains ""Marketing"")" -MembershipRuleProcessingState "On"
}
&$env:64bitPowerShellPath -WindowStyle Hidden -NonInteractive -Command $Script
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = $body
})
Check the group in the portal:

PowerShell DSC: xWebSite error : Desired website bindings are not valid for website

Scenario : Trying to create a https website with DSC using Azure Automation Account. I get the below error. Did you face the same scenario? Any help will be great.
HTTP bindings are working fine.
Windows 2012 R2
XWebAdministration Module version: 1.17.0.0
Error : PowerShell DSC resource MSFT_xWebsite failed to execute Test-TargetResource functionality with error message: Desired website bindings are not valid for website
DSC Node Config:
foreach ($Site in $Node.Sites)
{
xWebSite "$($Site.Name)WebSite"
{
Ensure = "Present"
Name = $Site.Name
ApplicationPool = "$($Site.Name)"
PhysicalPath = $Site.Path
State = 'Started'
DependsOn = "[xWebAppPool]$($Site.Name)AppPool"
BindingInfo = MSFT_xWebBindingInformation
{
Protocol = 'https'
Port = $Site.Port
CertificateStoreName = 'MY'
CertificateThumbprint = $(Get-ChildItem cert:\LocalMachine\My | where { $_.Subject -match "WMSvc" } | select -First 1).Thumbprint
}
}
DSC Configuration:
$data = #{
AllNodes = #(
#{
Sites = #(
#{Name="website1";Port="8643";Path="C:\inetpub\www\website1";Apps="App1","App2"}, #{Name="website2";Port="9643";Path="C:\inetpub\www\website2";Apps="App3","App4"})
})
}
Expressions that are used outside of a script-resource in DSC-configurations are executed on compilation. The following line would be executed on the management computer, where there certificate probably doesn't exist and will set the thumbprint in the .mof-file to NULL. You can verify this by looking in the generated mof-file.
CertificateThumbprint = $(Get-ChildItem cert:\LocalMachine\My | where { $_.Subject -match "WMSvc" } | select -First 1).Thumbprint
You need to specify the thumbprint as a string-value, or use a Script-resource to set the binding where you could run your Get-ChildItem-command as part of the SetScript-scriptblock.

new-item Host-Instance - BizTalk Powershell Extensions

I'm trying to use the Powershell Extensions to BizTalk 2010 to add a Host-Instance (the host already exists).
Add-PSSnapIn -Name BiztalkFactory.PowerShell.Extensions #NOTE: Must be in 32-bit version of Powershellto use this SnapIn
#get-PsSnapIn -registered ### list registered Snap-In's
$HostName = "TestNewHost"
$HostType = 1 # 1 = InProcess
$myNTHostGroupName = "BIZTALKDEV\Domain Users"
$AuthTrusted = $false
$domainName = "BizTalkDev"
$serverName = "BizTalkDev"
$defaultAdminUser = "Administrator"
$hostCredentials = $Host.ui.PromptForCredential("Logon Credentials","This account must have SQL Server permissions.", $domainName + "\" + $defaultAdminUser, "");
[String]$hostCredentialsPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($hostCredentials.Password));
#cd "Biztalk:\Platform Settings\Hosts"
#New-Item $HostName -HostType:$HostType -NtGroupName:$NTGroupName -AuthTrusted:$AuthTruste
#New-Item -path $hostName -HostType:$HostType -NtGroupName:$NTGroupName -AuthTrusted:$AuthTrusted
cd "BizTalk:\Platform Settings\Host Instances"
dir
Write-Host "Try to add New HostInstance=$hostName"
New-Item $hostName -HostName $hostName -Credentials $hostCredentials -RunningServer $serverName
dir
When I supply a valid domain user/password in the credentials, I get this error:
New-Item : Instance of the WMI class is not found.
No instance was found with the specified key. This could be the result of the instance being deleted by another BizTalk Admin session.At E:\CreateHost_PSSnapIn.ps1:27
char:1
If I leave off the -Credentials argument. It prompts me on that new-item for user/pass, and same error occurs. If I provide a totally bogus userid/pass, I still get the same error.
I found this issue. I had the wrong value for $servername, should have been "BizTalk2010Dev". I didn't catch that domain name and server name were different (this is a VM that a co-worker created).
So in summary, the error, while very ambiguous, was referring to the existing HostName being missing. All Host-Instances must be associated with an existing Host.