On previous post I have a code that use a text block to contain all the XML tags of a body, this method proved to be unsustainable, for some reasons variables cannot be parsed into the @" "@
block correctly.
So I used another method. Create the base XML, then read this base XML and add in the XML tags based on user input, then send the entire xml body to Tufin SecureChange.
Here’s the base XML:
<ticket>
<subject>Test</subject>
<priority>Normal</priority>
<workflow>
<name>Firewall Automation</name>
<uses_topology>true</uses_topology>
</workflow>
<steps>
<step>
<name>Open request</name>
<tasks>
<task>
<fields>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="multi_access_request">
<name>Firewall Rule</name>
</field>
</fields>
</task>
</tasks>
</step>
</steps>
<comments />
</ticket>
Here’s the code:
#ignore certificate validation add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $xpath = "ticket/steps/step/tasks/task/fields/field" function Obfuscate_Password($username){ if ((Test-Path .\fwr_s.do) -eq $true) { $password = Get-Content ".\fwr_s.do" | ConvertTo-SecureString $credential = New-Object System.Management.Automation.PSCredential($username,$password) } else { Read-Host $username -AsSecureString | ConvertFrom-SecureString | Out-File -NoClobber .\fwr_s.do #This is to allow time for the file to be written, otherwise there is a possibility that invoke-restmethod will throw an exception that is really weird. #Eg. Invoke-RestMethod : You must write ContentLength bytes to the request stream before calling [Begin]GetResponse. Start-Sleep -Seconds 2 $password = Get-Content ".\fwr_s.do" | ConvertTo-SecureString $credential = New-Object System.Management.Automation.PSCredential($username,$password) } return $credential.GetNetworkCredential().Password } function is_ipv4_address($newhost){ $ipcheck = ($newhost -as [IPaddress]) -as [Bool] if($ipcheck) { return $true } elseif($newhost -like "*/*" -or $newhost -match "[+\d].[+\d].[+\d].[+\d]-[+\d].[+\d].[+\d].[+\d]") { $cidr = $newhost.split("/") if($cidr[1] -ge '0' -and $cidr[1] -le '32') { return $true } elseif($newhost -like "*-*") { $ip = $newhost.split("-") $ip1 = $ip[0] -as [IPaddress] -as [Bool] $ip2 = $ip[1] -as [IPaddress] -as [Bool] if($ip -and $ip) { return $true } else { return $false } } else { return $false } } else { return $false } } [xml]$body = New-Object System.Xml.XmlDocument $body.Load(".\config.xml") #1 is the title, for user to see $a = 2 #source $b = 2 #destination $c = 2 #service $d = 2 #action $e = 2 #comment $src = @() # source ip address collection $dst = @() $srcHosts = @() # source hostnames collection $dstHosts = @() $services = @() # collection of services #$src_obj = @() #$dst_obj = @() $accessRequest = @() $xl = New-Object -ComObject Excel.Application $xl.Visible = $false # To prevent the excel from opening visibly. $wb = $xl.Workbooks.Open("C:\Tufin\tests\Rulebook.xlsx") $rule_name = $wb.Worksheets | Select-Object "Name" foreach($rule in $rule_name) { $ws = $wb.Sheets.item($rule.Name) #$ws = $wb.sheets.item("Rule1") if($ws.Range("A" + $a).Text -eq "" -or $ws.Range("B" + $b).Text -eq "" -or $ws.Range("C" + $c).Text -eq "") { break } # can use as a function for this part $access_request_node = $body.CreateNode("element","access_request",$NS_URI) $use_topology_node = $body.CreateNode("element","use_topology",$NS_URI) $users_node = $body.CreateNode("element","users",$NS_URI) $user_element = $body.CreateElement("user") $sources_node = $body.createNode("element","sources",$NS_URI) $destinations_node = $body.CreateNode("element","destinations",$NS_URI) $services_node = $body.CreateNode("element","services",$NS_URI) $action_node = $body.CreateNode("element","action",$NS_URI) $labels_node = $body.CreateNode("element","labels",$NS_URI) $body.ticket.steps.step.tasks.task.fields.field.AppendChild($access_request_node) $access_request_node.AppendChild($use_topology_node) $access_request_node.AppendChild($users_node) $users_node.AppendChild($user_element) $user_element.InnerText = "Any" $access_request_node.appendchild($sources_node) $access_request_node.appendchild($destinations_node) $access_request_node.AppendChild($services_node) $access_request_node.AppendChild($action_node) $action_node.InnerText = "Accept" $access_request_node.AppendChild($labels_node) $use_topology_node.InnerText = "true" while($true) { if($ws.Range("A" + $a).Text -ne "") # collect until an empty cell. { $srcHosts += $ws.Range("A" + $a).Text } else { break } $a += 1 } foreach($srcHost in $srcHosts) { if(is_ipv4_address($srcHost)){ $src += $srcHost } else { $srcHost + " resolving" >> "fwr_add.log" try{ $src += [System.Net.DNS]::GetHostEntry($srcHost).AddressList.IPAddressToString } catch { $err=$_.Exception $err.Message } } } foreach($src_ip in $src) { if($src_ip -like "*/*"){ $src_obj = $src_ip.split("/") $source_node = $body.createNode("element","source",$NS_URI) $source_node.SetAttribute("type","IP") $source_address_element = $body.CreateElement("ip_address") $source_address_cidr_element = $body.CreateElement("cidr") $sources_node.AppendChild($source_node) $source_node.AppendChild($source_address_element) $source_node.AppendChild($source_address_cidr_element) $source_address_element.InnerText = $src_obj[0] $source_address_cidr_element.InnerText = $src_obj[1] } else{ $source_node = $body.createNode("element","source",$NS_URI) $source_node.SetAttribute("type","IP") $source_address_element = $body.CreateElement("ip_address") $source_address_mask_element = $body.CreateElement("netmask") $sources_node.AppendChild($source_node) $source_node.AppendChild($source_address_element) $source_node.AppendChild($source_address_mask_element) $source_address_element.InnerText = $src_ip $source_address_mask_element.InnerText = "255.255.255.255" } } while($true) { if($ws.Range("B" + $b).Text -ne "") { $dstHosts += $ws.Range("B" + $b).Text } else { break } $b += 1 } foreach($dstHost in $dstHosts) { if(is_ipv4_address($dstHost)){ $dst += $dstHost } else{ $dst += [System.Net.DNS]::GetHostEntry($dstHost).AddressList.IPAddressToString } } foreach($dst_ip in $dst) { if($dst_ip -like "*/*"){ $dst_obj = $dst_ip.split("/") $destination_node = $body.CreateNode("element","destination",$NS_URI) $destination_node.SetAttribute("type","IP") $destination_address_element = $body.CreateElement("ip_address") $destination_address_mask_element = $body.CreateElement("netmask") $destination_address_cidr_element = $body.CreateElement("cidr") $destinations_node.AppendChild($destination_node) $destination_node.AppendChild($destination_address_element) $destination_node.AppendChild($destination_address_mask_element) $destination_node.AppendChild($destination_address_cidr_element) $destination_address_element.InnerText = $dst_obj[0] $destination_address_cidr_element.InnerText = $dst_obj[1] } else { $destination_node = $body.createNode("element","destination",$NS_URI) $destination_node.SetAttribute("type","IP") $destination_address_element = $body.CreateElement("ip_address") $destination_address_mask_element = $body.CreateElement("netmask") $destinations_node.AppendChild($destination_node) $destination_node.AppendChild($destination_address_element) $destination_node.AppendChild($destination_address_mask_element) $destination_address_element.InnerText = $dst_ip $destination_address_mask_element.InnerText = "255.255.255.255" } } while($true) { if($ws.Range("C" + $c).Text -ne "") { $services_s += @($ws.Range("C" + $c).Text) } else { break } $c += 1 } foreach($service in $services_s) { if($service.ToString().ToLower() -like "*tcp*") { $proto = "TCP" $port_num = $service.Replace("tcp","") } elseif($service.ToString().ToLower() -like "*udp*") { $proto = "UDP" $port_num = $service.Replace("udp","") } else { $proto = "TCP" $port_num = $service.Replace("tcp","") } $service_node = $body.CreateNode("element","service",$NS_URI) $service_node.SetAttribute("type","PROTOCOL") $protocol_element = $body.CreateElement("protocol") $port_element = $body.CreateElement("port") $services_node.AppendChild($service_node) $service_node.AppendChild($protocol_element) $service_node.AppendChild($port_element) $protocol_element.InnerText = $proto $port_element.InnerText = $port_num } $body.save("example_2.xml") $a = 2 #source $b = 2 #destination $c = 2 #service $d = 2 #action $e = 2 #comment $src = @() # source ip address collection $dst = @() $srcHosts = @() # source hostnames collection $dstHosts = @() $services_s = @() $services = @() } $xl.Workbooks.Close() $xl.Quit() [void][System.Runtime.Interopservices.Marshal]::FinalReleaseComObject($ws) [void][System.Runtime.Interopservices.Marshal]::FinalReleaseComObject($wb) [void][System.Runtime.Interopservices.Marshal]::FinalReleaseComObject($xl) [GC]::Collect() $usr = "admin" $pwd = Obfuscate_Password($usr) $cred = "${usr}:${pwd}" $bytes = [System.Text.Encoding]::ASCII.GetBytes($cred) $base64 = [System.Convert]::ToBase64String($bytes) $basicAuthValue = "Basic $base64" $headers = @{ Authorization = $basicAuthValue } #sleep to defeat the z monster = "You must write ContentLength bytes to the request stream before calling [Begin]GetResponse." Start-Sleep -Seconds 5 try { Invoke-RestMethod -Uri "https://tufin_address/securechangeworkflow/api/securechange/tickets/" -Method Post -ContentType "application/xml" -Headers $headers -Body $body } catch { $err=$_.Exception $err.Message }