Invoke-RestMethod not accepting letters with accent - web-services

I have a service on SharePoint 2013 which is responsible for managing custom menu.
I'm trying to use this service from PowerShell like this:
$MenuItem = New-Object -TypeName PSObject
$MenuItem | Add-Member -MemberType NoteProperty -Name LinkEN -Value $pageLink
$MenuItem | Add-Member -MemberType NoteProperty -Name LinkFR -Value $pageLink
$MenuItem | Add-Member -MemberType NoteProperty -Name TitleEN -Value $pageParam.ListTitle;
$MenuItem | Add-Member -MemberType NoteProperty -Name TitleFR -Value $pageParam.ListTitle;
$body = #{ _menuItem = $MenuItem; _parent = $null } | ConvertTo-Json
$url = $url + "/_vti_bin/MenuService.svc/AddMenuItem"
$result = Invoke-RestMethod -Uri $url -Method Post -UseDefaultCredentials -ContentType "application/json; charset=utf-8" -Body $body
It works fine up to the moment when I'm trying to send letter with an accent (e.g. è) through parameters (for example: $pageParam.ListTitle = "ètè").
In this situation I'm getting the following error:
Invoke-RestMethod : Request Error The server encountered an error
processing the request. See server logs for more details. At
FixDocumentPages.ps1:145 char:19
+ $result = Invoke-RestMethod -Uri $url -Method Post -UseDefaultCredential ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I have breakpoint in the server code, but it never gets that far.
Below are the SharePoint logs from this incident:
Entering monitored scope (Request(POST: http://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem )). Parent No Name=Request(POST:http ://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem) 4af4519d-0879-c02e-e1ad-bb2bcbb09abb Non-OAuth request. IsAuthenticated=False, UserIdentityName=, ClaimsCount=0 4af4519d-0879-c02e-e1ad-bb2bcbb09abb Micro Trace Tags: 0 nasq,1 agb9s 4af4519d-0879-c02e-e1ad-bb2bcbb09abb
Leaving Monitored Scope (Request(POST:http ://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem)). Execution Time=1,7839 4af4519d-0879-c02e-e1ad-bb2bcbb09abb
Entering monitored scope (Request(POST:http://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem)). Parent No Name=Request(POST:http ://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem) 4af4519d-087a-c02e-e1ad-b0990e08ad35 Micro Trace Tags: 0 nasq 4af4519d-087a-c02e-e1ad-b0990e08ad35
Leaving Monitored Scope (Request(POST:http://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem)). Execution Time=0,6495 4af4519d-087a-c02e-e1ad-b0990e08ad35
Entering monitored scope (Request(POST:http://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem)). Parent No Name=Request(POST:http ://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem) 4af4519d-087a-c02e-e1ad-bb3e80204d39 Non-OAuth request. IsAuthenticated=True, UserIdentityName=0#.w|test\administrator, ClaimsCount=29 4af4519d-087a-c02e-e1ad-bb3e80204d39 Micro Trace Tags: 0 nasq,1 agb9s 4af4519d-087a-c02e-e1ad-bb3e80204d39
Leaving Monitored Scope (Request(POST:http://wssppoc:5000/_vti_bin/MenuService.svc/AddMenuItem)). Execution Time=3,9189 4af4519d-087a-c02e-e1ad-bb3e80204d39 ContentIntegrationEngine: Execution started, flow identifier is 4659ab80-0016-499b-a3ff-c1961ca797bd.
Does anyone have any idea what could be wrong?

Sam answer is leading to the proper solution. Which is using:
[System.Text.Encoding]::UTF8.GetBytes()
Working code is:
$MenuItem = New-Object -TypeName PSObject
$MenuItem | Add-Member -MemberType NoteProperty -Name LinkEN -Value $pageLink
$MenuItem | Add-Member -MemberType NoteProperty -Name LinkFR -Value $pageLink
$MenuItem | Add-Member -MemberType NoteProperty -Name TitleEN -Value $pageParam.ListTitle;
$MenuItem | Add-Member -MemberType NoteProperty -Name TitleFR -Value $pageParam.ListTitle;
$body = #{ _menuItem = $MenuItem; _parent = $null } | ConvertTo-Json
$url = $url + "/_vti_bin/MenuService.svc/AddMenuItem"
$body = [System.Text.Encoding]::UTF8.GetBytes($body);
$result = Invoke-RestMethod -Uri $url -Method Post -UseDefaultCredentials -ContentType "application/json; charset=utf-8" -Body $body

Related

Gateway Binding using the API

I get an Error 400 (Bad Request) using the code below. I have looked at it for hours. Does anyone see anything wrong? Any suggestions? I've tried the suggestions in this link, but no luck: https://community.powerbi.com/t5/Developer/BindToGateway-Powershell-REST-API-POST-failing-Need-Help/m-p/852851
#Login to Power BI using PowerBIPS App registration.
Write-Host "Start Login"
$ApplicationId = "abc123"
$SecurePassword = "password" | ConvertTo-SecureString -AsPlainText -force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList
$ApplicationId, $SecurePassword
Connect-PowerBIServiceAccount -ServicePrincipal -Credential $credential -TenantId "ten123"
Write-Host "Login Success"
Write-Host "Get Workspace info for workspace: AC Common_TST"
$workspaceName = "AC Common_TST"
$datasetName = "DateDim"
$workspace = Get-PowerBIWorkspace -Name $workspaceName
$workspaceObject = ( Get-PowerBIWorkspace -Name "AC Common_TST" )
$groupid=$workspaceObject.id
$newGatewayId = "gatewayid" # the ID of PRDGateway1
$dataset = Get-PowerBIDataset -WorkspaceId $workspace.Id | Where-Object Name -eq $datasetName
$datasetid = $dataset.id
$workspaceId = $workspace.Id
Write-Host "GroupID is "$workspace.id
Write-Host "Dataset ID is "$dataset.id
# POST body
$postParams = #'
{
"gatewayObjectId": "gatewayid",
"datasourceObjectIds": [
"dsid"
]
}
'#
$jsonPostBody = $postParams | ConvertTo-JSON
$uri = "https://api.powerbi.com/v1.0/myorg/groups/$workspaceid/datasets/$datasetId/Default.BindToGateway"
Invoke-PowerBIRestMethod -URL $uri -Method POST -Body $jsonPostBody
Resolve-PowerBIError -Last

powershell extract chapter index

I have a file that looks like this
1
Account Policies
1.1
Password Policy
1.1.1
(L1) Ensure 'Enforce password history' is set to '24 or more password(s)' (Automated)


1.1.2
(L1) Ensure 'Maximum password age' is set to '365 or fewer days, but not 0' (Automated)


1.1.3
(L1) Ensure 'Minimum password age' is set to '1 or more day(s)' (Automated)


1.1.4
(L1) Ensure 'Minimum password length' is set to '14 or more character(s)' (Automated)


1.1.5
(L1) Ensure 'Password must meet complexity requirements' is set to 'Enabled' (Automated)


1.1.6
(L1) Ensure 'Store passwords using reversible encryption' is set to 'Disabled' (Automated)


1.2
Account Lockout Policy
1.2.1
(L1) Ensure 'Account lockout duration' is set to '15 or more minute(s)' (Automated)


Im trying to use regex to look for the number patterns and parse the file so my output looks similar to this
1 Account Policies
1.1.1 Enforce password history 24 or more password(s) DC and Member Servers
1.1.2 Maximum password age 365 or fewer days, but not 0 DC and Member Servers
1.1.3 Minimum password age 1 or more day(s) DC and Member Servers
1.1.4 Minimum password length 14 or more character(s) DC and Member Servers
1.1.5 Password must meet complexity requirements Enabled DC and Member Servers
1.1.6 Store passwords using reversible encryption Disabled DC and Member Servers
1.2.1 Account lockout duration 15 or more minute(s) DC and Member Servers
1.2.2 Account lockout threshold 5 or fewer invalid logon attempt(s), but not 0 DC and Member Servers
1.2.3 Reset account lockout counter after 15 or more minute(s) DC and Member Servers
2 Local Policies
The problem is the output doesnt give 1.1 or 2.1. Only 1 and 1.1.1 and 2 and 2.2.1. Im missing a bunch of sections.
Any ideas?
Thank you!
Here is the code I have so far.
$parse=Get-Content '.\raw2.txt'
$allpolicies = #()
foreach($line in $parse){
$server="DC and Member Servers"
if($line -match "^(?<!\S)\d(?!\S)"){
$section=$line
continue
}
if($section -match "^(?<!\S)\d(?!\S)"){
$policy = $line
$setting = ""
$server=""
$obj=New-Object psobject
$obj | Add-Member -MemberType NoteProperty -Name section -Value $section
$obj | Add-Member -MemberType NoteProperty -Name policy -Value $policy
$obj | Add-Member -MemberType NoteProperty -Name Setting -Value $setting
$obj | Add-Member -MemberType NoteProperty -Name server -Value $server
$allpolicies += $obj
$section=$null
$policy=""
$Setting = ""
continue
}
if(($line -match "\d{1,}.\d{1,}.\d{1,}")){
$section=$line
}
if(($line -match "(L1)") -or ($line -match "(L2)")){
$splitline=$line -split ("'")
$policy=$splitline[1]
$setting=$splitline[3]
if($line -match "(DC only)"){
$server="DC Only"
}
if($line -match "(MS only)"){
$server="MemberServer Only"
}
$obj=New-Object psobject
$obj | Add-Member -MemberType NoteProperty -Name section -Value $section
$obj | Add-Member -MemberType NoteProperty -Name policy -Value $policy
$obj | Add-Member -MemberType NoteProperty -Name Setting -Value $setting
$obj | Add-Member -MemberType NoteProperty -Name server -Value $server
$allpolicies += $obj
$section=$null
}
}
$allpolicies | Out-GridView

Creating AWS SSM Document to run Powershell commands

Im trying to make an SSM Document that runs the following Powershell script:
New-Item -ItemType Directory -Force -Path C:\temp
$checkupdatesscript = "`$UpdateSession = New-Object -ComObject Microsoft.Update.Session"
$checkupdatesscript | Out-File C:\temp\checkwindowsupdates.ps1
Add-Content -Path C:\temp\checkwindowsupdates.ps1 -Value "`$UpdateSearcher = `$UpdateSession.CreateupdateSearcher()"
Add-Content -Path C:\temp\checkwindowsupdates.ps1 -Value "`$Updates = #(`$UpdateSearcher.Search(`"IsHidden=0 and IsInstalled=0`").Updates)"
Add-Content -Path C:\temp\checkwindowsupdates.ps1 -Value "`$Updates | Select-Object Title > C:\temp\windowsupdates.txt"
$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument "C:\temp\checkwindowsupdates.ps1"
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5)
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "Check Windows Updates" -Description "checks for any outstanding windows updates every 5 minutes"
I have created the following SSM Document in YAML:
---
schemaVersion: "2.2"
description: "Creates script and scheduled task to check for any outstanding windows updates every 5 minutes"
mainSteps:
- action: "aws:runPowerShellScript"
name: "RunCommands"
inputs:
runCommand:
- "New-Item -ItemType Directory -Force -Path C:\temp"
- "$checkupdatesscript = \"`$UpdateSession = New-Object -ComObject Microsoft.Update.Session\""
- "$checkupdatesscript | Out-File C:\temp\checkwindowsupdates.ps1"
- "Add-Content -Path C:\temp\checkwindowsupdates.ps1 -Value \"`$UpdateSearcher = `$UpdateSession.CreateupdateSearcher()\""
- "Add-Content -Path C:\temp\checkwindowsupdates.ps1 -Value \"`$Updates = #(`$UpdateSearcher.Search(`\"IsHidden=0 and IsInstalled=0`\").Updates)\""
- "Add-Content -Path C:\temp\checkwindowsupdates.ps1 -Value \"`$Updates | Select-Object Title > C:\temp\windowsupdates.txt\""
- "$action = New-ScheduledTaskAction -Execute \"Powershell.exe\" -Argument \"C:\temp\checkwindowsupdates.ps1\""
- "$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5)"
- "Register-ScheduledTask -Action $action -Trigger $trigger -TaskName \"Check Windows Updates\" -Description \"checks for any outstanding windows updates every 5 minutes\""
But am receiving an error when attempting to create the document. The error is "InvalidDocumentContent: null"
I am assuming I have messed up the YAML but can't seem to figure out what.
The issue did lie within the YAML. I had not escaped the backslashes in the file paths. The correct yaml should look like this:
---
schemaVersion: "2.2"
description: "Creates script and scheduled task to check for any outstanding windows updates every 5 minutes"
mainSteps:
- action: "aws:runPowerShellScript"
name: "RunCommands"
inputs:
runCommand:
- "New-Item -ItemType Directory -Force -Path C:\\temp"
- "$checkupdatesscript = \"`$UpdateSession = New-Object -ComObject Microsoft.Update.Session\""
- "$checkupdatesscript | Out-File C:\\temp\\checkwindowsupdates.ps1"
- "Add-Content -Path C:\\temp\\checkwindowsupdates.ps1 -Value \"`$UpdateSearcher = `$UpdateSession.CreateupdateSearcher()\""
- "Add-Content -Path C:\\temp\\checkwindowsupdates.ps1 -Value \"`$Updates = #(`$UpdateSearcher.Search(`\"IsHidden=0 and IsInstalled=0`\").Updates)\""
- "Add-Content -Path C:\\temp\\checkwindowsupdates.ps1 -Value \"`$Updates | Select-Object Title > C:\\temp\\windowsupdates.txt\""
- "$action = New-ScheduledTaskAction -Execute \"Powershell.exe\" -Argument \"C:\\temp\\checkwindowsupdates.ps1\""
- "$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5)"
- "Register-ScheduledTask -Action $action -Trigger $trigger -TaskName \"Check Windows Updates\" -Description \"checks for any outstanding windows updates every 5 minutes\""

AWS - Security groups reports powershell

I'm trying to pull several region such as us-west-1, us-west-2 or everything security groups from aws but it doesn't seem to be working and it is getting the region that was defined in ./config
is there a way to pull it from all region? and how should i do it?
that is what i have done so far.
Import-Module AWSPowershell
> $EC2GroupList = Get-EC2SecurityGroup | Select-Object Description, GroupId, GroupName,
> IpPermission, IpPermissionsEgress, VpcId
>
> $ChangeList = #()
>
> $GroupsCount = ($EC2GroupList | Measure-Object).Count
> foreach($SecGroup in $EC2GroupList) {
> $Description = $SecGroup.IpPermission.Ipv4Ranges.Description
> $GroupID = $SecGroup.GroupId
> $SecurityGroupName = $SecGroup.GroupName
> $SourceIP = $SecGroup.IpPermission.Ipv4Ranges.CidrIp
> $FromPort = $SecGroup.IpPermission.FromPort
> $ToPort = $SecGroup.IpPermission.ToPort
> $Protocol = $SecGroup.IpPermission.IpProtocol
>
> echo $GroupsCount
>
> if($FromPort -ne $null) {
> $NewObject = new-object -TypeName PSobject
> #$NewObject | Add-Member NoteProperty -Name Region -Value
> $NewObject | Add-Member NoteProperty -Name Description -Value $Description
> $NewObject | Add-Member NoteProperty -Name GroupID -Value $GroupID
> $NewObject | Add-Member NoteProperty -Name SecurityGroupName -Value $SecurityGroupName
> $NewObject | Add-Member NoteProperty -Name SourceIP -Value $SourceIP
> $NewObject | Add-Member NoteProperty -Name FromPort -Value $FromPort
> $NewObject | Add-Member NoteProperty -Name ToPort -Value $ToPort
> $NewObject | Add-Member NoteProperty -Name Protocol -Value $Protocol
> $ChangeList += $NewObject
> }
> }
>
> echo $ChangeList
The API calls are mostly region specific except for a few global services so you need make a call per region generally. You can override the region like this: Get-EC2SecurityGroup -region eu-west-2.
Heres a rough sample
# wrap up your existing code in a function for later...
function Get-RegionSecurityGroupReport{
Param([String] $region = 'eu-west-1');
# replace with your code but pass $region when calling any APIs e.g.
$EC2GroupList = Get-EC2SecurityGroup -region $region | Select-Object ...
# return current regions data
return $EC2GroupList;
}
# Setup the script
$activeRegions = #('eu-west-1', 'eu-west-2');
$results = #();
# loop through regions and execute your function with each region in turn...
$activeRegions | % {
Write-Host "Processing region $($_)";
$results += Get-RegionSecurityGroupReport -region $_;
}
# your multi regional report:
Write-Host $results
There is an API call DescribeRegions gets you all the regions available and the corresponding aws cli call describe-regions.
I found this blog post aws-regions-and-windows-powershell and the corresponding call Get-EC2Region.

vCenter VM permission query using Powershell / PowerCLI

I've been trying to use Powershell with imported PowerCLI commands for VMware administration and I've hit a snag. What I'm trying to do is query all VM's in a location (doesn't matter where), and for every VM I want the group with "Virtual Machine User with Snapshot" permission, and then use that group name to run a Get-ADGroupMembers query for everyone in that group. I also have to remove the domain prefix from the AD query, which would otherwise cause an error.
After some more playing around with outputting hash table information into the csv, as opposed to 'SystemObject[]', I finally got the script so it doesn't return errors EXCEPT on VM's where there is more than one group. It throws an error but the script continues, and just outputs the members of the first group.
How do I get it to do a recursive AD query for every group that is pulled into the owner groups hashtable? The output would be the same as for all the other VM's, just with a line for each group and members.
$AllVMs = #()
$vms = get-vm * -Location datacenter
foreach ($vm in $vms)
{
$owners = Get-VIPermission $vm.name | where-object {$_.role -eq "virtual machine user with snapshot"}
foreach ($owner in $owners)
{
$members = Get-ADGroupMember ($owners.principal -replace '^prefix\\')
$temp = New-Object psobject |
Add-Member Noteproperty "Name" -value $vm.name -PassThru |
Add-Member Noteproperty "Owner" -value (#($owners.principal) -join ',') -PassThru |
Add-Member Noteproperty "Members" -value (#($members.SamAccountName) -join ',') -passthru
$AllVMs+=$temp
}
$AllVMs | Export-Csv -Path c:\users\me\desktop\AllVMs.csv
I was playing around with it some more today and figured it out! I'm running the script right now against a datacenter with 350+ machines so technically I don't know 100% that it works, but it worked against 3 machines :-) I also added a line to list every machine that's owned by more than one group - handy for troubleshooting. Here's the script:
$AllVMs = #()
$vms = get-vm -Location DATACENTER
foreach ($vm in $vms)
{
$owners = #(Get-VIPermission $vm.name | where-object {$_.role -eq "virtual machine user with snapshot"})
if ($owners.count -gt 1) {write-host "** Note ** '$vm' has"$owners.count "owner groups"}
foreach ($owner in $owners)
{
$members = Get-ADGroupMember ($owner.principal -replace '^prefix\\')
$temp = New-Object psobject |
Add-Member Noteproperty "Name" -value $vm.name -PassThru |
Add-Member Noteproperty "Owner" -value (#($owner.principal) -join ',') -PassThru |
Add-Member Noteproperty "Members" -value (#($members.SamAccountName) -join ',') -PassThru
$AllVMs+=$temp
}
}
$AllVMs
Change $owners.principal to $owner.principal after $members = Get-ADGroupMember? In case you have nested AD groups, Get-ADGroupMember has a -Recursive parameter.