├── .devcontainer
├── devcontainer.json
└── Dockerfile
├── examples
├── application-bulk-import.csv
├── archive-flows-to-vrli
│ ├── config.json
│ ├── vrealize-log-insight.ps1
│ └── vrni-archive-flows-to-vrli.ps1
├── datasource-bulk-set-snmp.csv
├── export-flows.ps1
├── get-bandwidth-usage-per-ip.ps1
├── datasource-bulk-set-snmp.ps1
├── datasource-bulk-import.csv
├── application-bulk-import.ps1
├── cmdb-import-from-itop.ps1
├── datasource-bulk-import.ps1
└── cmdb-import-from-servicenow.ps1
├── ToDo.md
├── .vscode
└── settings.json
├── extract-example-metadata.sh
├── publish
├── Publish.ps1
├── Include.ps1
└── psgallery
│ └── PowervRNI
│ └── PowervRNI.psd1
├── EXAMPLES.md
├── ChangeLog.md
├── README.md
├── PowervRNI.psd1
└── LICENSE.md
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "PowervRNI Development Container",
3 | "dockerFile": "Dockerfile",
4 | "postCreateCommand": "pwsh",
5 | "extensions": [
6 | "ms-vscode.powershell"
7 | ]
8 | }
--------------------------------------------------------------------------------
/examples/application-bulk-import.csv:
--------------------------------------------------------------------------------
1 | Application;Tier;Security Group;VM Names
2 | App01;Web;;App01-VM1-Web,App01-VM2-Web
3 | App01;App;SG-3Tier-App;App01-VM*-App
4 | App01;DB;SG-App01-DB;
5 | App02;NoTier;SG-App02;
6 | App03;Web;;App03-Web*
7 | App03;DB;;App03-DB*
--------------------------------------------------------------------------------
/examples/archive-flows-to-vrli/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "vrni_server": "my-vrni-platform.lab",
3 | "vrni_credentials_file": "credentials.xml",
4 | "vrni_domain": "local",
5 | "vrli_server": "my-vrli-server",
6 | "cache_file": "flow-cache.json",
7 | "last_flows_ts": 1579273407
8 | }
9 |
--------------------------------------------------------------------------------
/examples/datasource-bulk-set-snmp.csv:
--------------------------------------------------------------------------------
1 | Nickname;NewSnmpCommunity
2 | cat3k.lab.local;public
3 | cat45k.lab.local;public
4 | cat65k.lab.local;public
5 | n5k.lab.local;public
6 | n7k.lab.local;public
7 | n9k.lab.local;public
8 | arista.lab.local;public
9 | dellf10mlx10.lab.local;public
10 | dellp8024.lab.local;public
11 | dell54048.lab.local;public
12 | dell29100.lab.local;public
13 | dell56000.lab.local;public
14 | brocade.lab.local;public
15 | juniper.lab.local;public
16 | ucs.lab.local;public
--------------------------------------------------------------------------------
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/powershell:ubuntu16.04
2 |
3 | # Set working directory so stuff doesn't end up in /
4 | WORKDIR /root
5 |
6 | # Configure apt
7 | ENV DEBIAN_FRONTEND=noninteractive
8 | RUN apt-get update && apt-get -y install --no-install-recommends apt-utils 2>&1
9 |
10 | # Install git, process tools, lsb-release (common in install instructions for CLIs)
11 | RUN apt-get -y install git procps lsb-release
12 |
13 | # Trust PSGallery
14 | SHELL [ "pwsh", "-command" ]
15 | RUN Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
16 |
17 | CMD ["/usr/bin/pwsh"]
18 |
--------------------------------------------------------------------------------
/ToDo.md:
--------------------------------------------------------------------------------
1 | ## ToDo items/ideas
2 |
3 | - \[enhancement] improve cmdlets that take `-StartTime` / `-EndTime` parameters to take actual `DateTime` objects to improve the user experience (they can pass the more "natural"-in-PowerShell `Get-Date "13 Jun 2017"` as a value, instead of needing to pass a "seconds since 01 Jan 1970" value, or even think about less-legible epoch-based time)
4 | - \[enhancement] add `-WhatIf` support to Set-, Remove-, etc. cmdlets (via `SupportsShouldProcess` directive in `CmdletBinding` and `$PSCmdlet.ShouldProcess()` in the body), and maybe add `ConfirmImpact` of `High` to destructive cmdlets (`Remove-vRNI*`, for example), as described at [https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.confirmimpact?view=powershellsdk-1.1.0](https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.confirmimpact?view=powershellsdk-1.1.0)
5 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "editor.formatOnSave": true,
4 | "files.trimTrailingWhitespace": true,
5 | "editor.tabSize": 2,
6 | "editor.insertSpaces": true,
7 | "editor.detectIndentation": false,
8 | "[markdown]": {
9 | "files.trimTrailingWhitespace": false,
10 | },
11 | "yaml.customTags": [
12 | "!And",
13 | "!And sequence",
14 | "!If",
15 | "!If sequence",
16 | "!Not",
17 | "!Not sequence",
18 | "!Equals",
19 | "!Equals sequence",
20 | "!Or",
21 | "!Or sequence",
22 | "!FindInMap",
23 | "!FindInMap sequence",
24 | "!Base64",
25 | "!Join",
26 | "!Join sequence",
27 | "!Cidr",
28 | "!Ref",
29 | "!Sub",
30 | "!Sub sequence",
31 | "!GetAtt",
32 | "!GetAZs",
33 | "!ImportValue",
34 | "!ImportValue sequence",
35 | "!Select",
36 | "!Select sequence",
37 | "!Split",
38 | "!Split sequence"
39 | ]
40 | }
--------------------------------------------------------------------------------
/extract-example-metadata.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo "# PowervRNI - Examples" > EXAMPLES.md
4 |
5 | EXAMPLE_FILES="examples/*.ps1 examples/archive-flows-to-vrli/*.ps1"
6 | for example in $EXAMPLE_FILES
7 | do
8 | #echo "Processing $example file..."
9 | # see if example header is present
10 | LINE=`grep "Example:" $example`
11 | if [ -n "$LINE" ]
12 | then
13 | EXAMPLE_NAME=`echo $LINE | sed -e 's/^# Example:\ *//'`
14 | echo "## ${example}" >> EXAMPLES.md
15 | echo "### ${EXAMPLE_NAME}" >> EXAMPLES.md
16 |
17 | # sed -n '1!p' = cut first line ("START Description")
18 | # sed '$d' = cut last line ("END Description")
19 | # sed 's/^..//' = remove the comments "# "
20 | EXAMPLE_DESC=`sed -n '/START Description/,/END Description/p' $example | sed -n '1!p' | sed '$d' | sed 's/^..//'`
21 | echo $EXAMPLE_DESC >> EXAMPLES.md
22 |
23 | example_file=`echo $example | sed -e 's/^examples\/\ *//'`
24 |
25 | #echo "
"
26 | #echo " | ${example_file} | "
27 | #echo " ${EXAMPLE_NAME} | "
28 | #echo " ${EXAMPLE_DESC} | "
29 | #echo "
"
30 | fi
31 | done
--------------------------------------------------------------------------------
/examples/export-flows.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Examples
2 | #
3 | # Example: Exporting network flows
4 | #
5 | # START Description
6 | # This script outputs flows in a certain time range.
7 | # END Description
8 | #
9 | # Martijn Smit (@smitmartijn)
10 | # msmit@vmware.com
11 | # Version 1.0
12 |
13 | param (
14 | [parameter(Mandatory = $false, ValueFromPipeLine = $true, ValueFromPipeLineByPropertyName = $true)]
15 | [ValidateNotNullOrEmpty()]
16 | [int]$StartTime = ([Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s")) - 60), # default to an hour window
17 | [parameter(Mandatory = $false, ValueFromPipeLine = $true, ValueFromPipeLineByPropertyName = $true)]
18 | [ValidateNotNullOrEmpty()]
19 | [int]$EndTime = [Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s")),
20 | [parameter(Mandatory = $false, ValueFromPipeLine = $true, ValueFromPipeLineByPropertyName = $true)]
21 | [ValidateNotNullOrEmpty()]
22 | [int]$Limit = 9999
23 | )
24 |
25 | if ($null -eq $defaultvRNIConnection) {
26 | Write-Host "Please connect to a Network Insight instance, using Connect-vRNIServer or Connect-NIServer!"
27 | exit;
28 | }
29 |
30 | $flows = Get-vRNIFlow -StartTime $StartTime -EndTime $EndTime -Limit $Limit -Debug
31 | $flows
32 | $flows.Count
33 |
34 | foreach ($flow in $flows) {
35 | }
36 |
37 | if ($Limit -lt $flows.Count) {
38 | Write-Host -ForegroundColor "red" "The current limit ($Limit) is lower than the amount of flows in the system. Consider raising the limit."
39 | }
--------------------------------------------------------------------------------
/publish/Publish.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Publishing:
2 | #
3 | # - Generate a new manifest
4 | # - Publish it to PowerShell Gallery
5 | #
6 | # Martijn Smit (@smitmartijn)
7 | # msmit@vmware.com
8 | # Version 1.0
9 |
10 | param (
11 | # Required API key to upload to PowerShell Gallery.
12 | [Parameter (Mandatory = $true)]
13 | [string]$NuGetApiKey
14 | )
15 |
16 | # Source the Include.ps1 file for settings
17 | . ./Include.ps1
18 |
19 | # Append the current build number on the version number. For this, we need git.
20 | # The build number is correlated on how many commits there are.
21 |
22 | # Check if we have git
23 | try { if (Get-Command git) { <# we have git, so continue! #> } }
24 | catch { throw "For this script to run, we need git. I couldn't find git." }
25 |
26 | # Get build number
27 | $BuildNumber = (git log --oneline).Count
28 | # Format version number
29 | $PowervRNI_Version = $PowervRNI_Version + '.' + $BuildNumber.ToString().Trim()
30 | # Test version
31 | if (-not ($PowervRNI_Version -as [version])) {
32 | throw "$PowervRNI_Version is not a valid version number. Try again."
33 | }
34 | # Add the version to the manifest options
35 | $Manifest_Common.Add("ModuleVersion", $PowervRNI_Version)
36 |
37 | # Get current working directory
38 | $currentPath = split-path $MyInvocation.MyCommand.Path
39 |
40 | # Generate new manifest file
41 | New-ModuleManifest -Path "$currentPath/../PowervRNI.psd1" -PowerShellVersion '6.0' @Manifest_Common
42 | # Convert to UTF8
43 | $content = Get-Content "$currentPath/../PowervRNI.psd1"
44 | [System.IO.File]::WriteAllLines("$currentPath/../PowervRNI.psd1", $content)
45 |
46 | # Copy module file to publish directory
47 | Copy-Item -Path "$currentPath/../PowervRNI.psm1" "$currentPath/psgallery/PowervRNI/"
48 | # Copy manifest file to publish directory
49 | Copy-Item -Path "$currentPath/../PowervRNI.psd1" "$currentPath/psgallery/PowervRNI/"
50 |
51 | Publish-Module -NuGetApiKey $NuGetApiKey -Path "$currentPath/psgallery/PowervRNI" -ReleaseNotes $Manifest_Common.ReleaseNotes
52 |
53 | Write-Host -ForegroundColor Yellow "PowervRNI $PowervRNI_Version is now published to the PowerShell Gallery! Also push the new files to GitHub."
54 |
--------------------------------------------------------------------------------
/EXAMPLES.md:
--------------------------------------------------------------------------------
1 | # PowervRNI - Examples
2 | ## examples/application-bulk-import.ps1
3 | ### Adding applications in bulk
4 | This script uses an input CSV (example: application-bulk-import.csv) to add multiple vRealize Network Insight Applications. Modify application-bulk-import.csv to contain your applications and application tiers, along with either the NSX Security Group or the VM names. Then run this script with the param -ApplicationsCSV to your CSV.
5 | ## examples/cmdb-import-from-itop.ps1
6 | ### Import Applications from iTop
7 | Retrieves applications from the CMDB iTop, and imports them into vRNI.
8 | ## examples/cmdb-import-from-servicenow.ps1
9 | ### Import Applications from ServiceNow
10 | Retrieves applications from the CMDB ServiceNow, and imports them into vRNI. Note: is now a native vRNI feature, the script is still here to serve as an example.
11 | ## examples/datasource-bulk-import.ps1
12 | ### Adding datasources in bulk
13 | This script uses an input CSV (example: datasource-bulk-import.csv) to add multiple vRealize Network Insight Data Sources. Modify datasource-bulk-import.csv to contain your own data sources (vCenters, NSX, switches, firewalls) and run this script with the param -DatasourcesCSV to your CSV.
14 | ## examples/datasource-bulk-set-snmp.ps1
15 | ### Changing SNMP configs of multiple switch devices
16 | This script uses an input CSV (example: datasource-bulk-snmp.csv) to configure multiple vRealize Network Insight Data Sources SNMP Values. Modify datasource-bulk-snmp.csv to contain your own data sources and run this script with the param -DatasourcesCSV to your CSV. Based off Martijn Smit bulk data source import script.
17 | ## examples/export-flows.ps1
18 | ### Exporting network flows
19 | This script outputs flows in a certain time range.
20 | ## examples/get-bandwidth-usage-per-ip.ps1
21 | ### Billing Use Case
22 | Gets a list of IPs with their respective bandwidth usage, which can be used for billing purposes (ISPs).
23 | ## examples/archive-flows-to-vrli/vrni-archive-flows-to-vrli.ps1
24 | ### Archiving vRealize Network Insight flows to vRealize Log Insight
25 | This script connects to vRNI, retrieves the flows within a time window (the last time this script was run and now), then checks whether the flow is located in the cache (more info in comments of cache code), and if not, gathers metadata (VM & L2 network name), and finally sends the flow to vRLI using Send-vRLIMessage from vrealize-log-insight.ps1
26 |
--------------------------------------------------------------------------------
/examples/get-bandwidth-usage-per-ip.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Examples
2 | #
3 | # Example: Billing Use Case
4 | #
5 | # START Description
6 | # Gets a list of IPs with their respective bandwidth usage, which can be used for billing purposes (ISPs).
7 | # END Description
8 | #
9 | # Martijn Smit (@smitmartijn)
10 | # msmit@vmware.com
11 | # Version 1.0
12 |
13 |
14 | param (
15 | [Parameter (Mandatory = $false)]
16 | # The epoch timestamp of when to start looking up records
17 | [int]$StartTime = ([Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s")) - 86400), # default to a day window
18 | [Parameter (Mandatory = $false)]
19 | # The epoch timestamp of when to stop looking up records
20 | [int]$EndTime = [Math]::Floor([decimal](Get-Date(Get-Date).ToUniversalTime()-uformat "%s"))
21 | )
22 |
23 | # If we want to select flows in a time slot, make sure the end time is later then the start time
24 | if ($StartTime -gt $EndTime) {
25 | throw "Param StartTime cannot be greater than EndTime"
26 | }
27 |
28 | if (!$defaultvRNIConnection) {
29 | throw "Use Connect-vRNIServer or Connect-NIServer to connect to Network Insight first!"
30 | }
31 |
32 | # Loop through these IPs and get their download/upload bytes
33 | $IPs_to_lookup = @("10.8.20.20", "10.8.20.66")
34 | foreach ($ip_address in $IPs_to_lookup) {
35 | # Get download bytes first
36 | $requestBody = @{
37 | entity_type = 'Flow'
38 | filter = "destination_ip.ip_address = '$ip_address'"
39 | aggregations = @( @{
40 | field = "flow.totalBytes.delta.summation.bytes"
41 | aggregation_type = "SUM"
42 | } )
43 | start_time = $StartTime
44 | end_time = $EndTime
45 | }
46 |
47 | $listParams = @{
48 | Connection = $defaultvRNIConnection
49 | Method = 'POST'
50 | Uri = "/api/ni/search/aggregation"
51 | Body = ($requestBody | ConvertTo-Json)
52 | }
53 |
54 | $result = Invoke-vRNIRestMethod @listParams
55 | $download_bytes = $result.aggregations.value
56 |
57 | # Now get upload bytes
58 | $requestBody = @{
59 | entity_type = 'Flow'
60 | filter = "source_ip.ip_address = '$ip_address'"
61 | aggregations = @( @{
62 | field = "flow.totalBytes.delta.summation.bytes"
63 | aggregation_type = "SUM"
64 | } )
65 | start_time = $StartTime
66 | end_time = $EndTime
67 | }
68 |
69 | $listParams = @{
70 | Connection = $defaultvRNIConnection
71 | Method = 'POST'
72 | Uri = "/api/ni/search/aggregation"
73 | Body = ($requestBody | ConvertTo-Json)
74 | }
75 |
76 | $result = Invoke-vRNIRestMethod @listParams
77 | $upload_bytes = $result.aggregations.value
78 |
79 | Write-Host "IP: $ip_address - Download bytes: $download_bytes - Upload bytes: $upload_bytes"
80 | }
81 |
--------------------------------------------------------------------------------
/examples/datasource-bulk-set-snmp.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Examples
2 | #
3 | # Example: Changing SNMP configs of multiple switch devices
4 | #
5 | # START Description
6 | # This script uses an input CSV (example: datasource-bulk-snmp.csv) to configure multiple vRealize Network Insight
7 | # Data Sources SNMP Values. Modify datasource-bulk-snmp.csv to contain your own data sources and run this script
8 | # with the param -DatasourcesCSV to your CSV. Based off Martijn Smit bulk data source import script.
9 | # END Description
10 |
11 | param (
12 | [parameter(Mandatory = $true, ValueFromPipeLine = $true, ValueFromPipeLineByPropertyName = $true)]
13 | [ValidateNotNullOrEmpty()]
14 | [string]$DatasourcesCSV
15 | )
16 |
17 | # Test CSV existance
18 | if (!(Test-Path $DatasourcesCSV)) {
19 | throw "[$(Get-Date)] CSV with data sources not found! ($DatasourcesCSV)"
20 | }
21 |
22 | if (!$defaultvRNIConnection) {
23 | throw "[$(Get-Date)] Please connect to vRealize Network Insight [Cloud] first! (Connect-vRNIServer or Connect-NIServer)"
24 | }
25 |
26 | # Put all datasources into a hash array first
27 | Write-Host "[$(Get-Date)] Getting a list of all data sources first.."
28 | $datasources = @{}
29 | $datasources_raw = Get-vRNIDataSource -DataSourceType ciscoswitch # If you want to speed this up, add i.e. -DatasourceType ciscoswitch for only Cisco switches.
30 | Write-Host "[$(Get-Date)] Found $($datasources_raw.Count) data sources!" -ForegroundColor "green"
31 |
32 | # Save the datasources in a hash, using the nickname as a key to identify it against the CSV
33 | foreach ($ds in $datasources_raw) {
34 | $datasources.Add($ds.nickname, $ds)
35 | }
36 |
37 | $updates_failed = @{}
38 | # Read the CSV into memory (using delimiter ';' so you can use Excel to modify it)
39 | $csvList = Import-CSV $DatasourcesCSV -Delimiter ';'
40 | $successfully_updated = 0
41 | Write-Host "[$(Get-Date)] The CSV has $($csvList.Count) data sources, starting to update those.."
42 | foreach ($csvLine in $csvList) {
43 | Write-Host "[$(Get-Date)] Setting SNMP for Data Source with Nickname of $($csvLine.Nickname).."
44 |
45 | if (!$datasources.ContainsKey($csvLine.Nickname)) {
46 | Write-Host "Datasource with nickname $($csvLine.Nickname) not found; skipping!" -ForegroundColor "red"
47 | continue
48 | }
49 |
50 | # TODO: SNMPv3 support
51 | # Run!
52 | try {
53 | $ds = $datasources.Item($csvLine.Nickname)
54 | $result = ($ds | Set-vRNIDataSourceSNMPConfig -Enabled $true -Community $csvLine.NewSnmpCommunity)
55 | $successfully_updated++
56 | Write-Host "Done updating $($csvLine.Nickname)!" -ForegroundColor "green"
57 | }
58 | catch {
59 | Write-Host "Error updating $($csvLine.Nickname): $($_)" -ForegroundColor "red"
60 | $updates_failed.Add($csvLine.Nickname, $_)
61 | }
62 | }
63 |
64 | Write-Host "Sucessfully updated $($successfully_updated) data sources!" -ForegroundColor "green"
65 | if ($updates_failed.Count -gt 0) {
66 | Write-Host "Error updating these datasources:" -ForegroundColor "red"
67 | $updates_failed.Keys | % { Write-Host " - $($_) with error: $($updates_failed.Item($_))" -ForegroundColor "red" }
68 | }
--------------------------------------------------------------------------------
/examples/datasource-bulk-import.csv:
--------------------------------------------------------------------------------
1 | DatasourceType;IP;Username;Password;Nickname;NSX_ENABLE_CENTRAL_CLI;NSX_ENABLE_IPFIX;NSX_VCENTER_NICKNAME;CISCO_SWITCHTYPE;DELL_SWITCHTYPE;SnmpCommunity
2 | vcenter;172.16.0.11;administrator@vsphere.local;MyPassword;vcenter.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;""
3 | nsxv;172.16.0.11;admin;MyPassword;nsx.lab.local;TRUE;TRUE;vcenter.lab.local;onlyusedforCisco;onlyusedforDell;""
4 | ciscoswitch;172.16.0.11;admin;MyPassword;cat3k.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;CATALYST_3000;onlyusedforDell;public
5 | ciscoswitch;172.16.0.11;admin;MyPassword;cat45k.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;CATALYST_4500;onlyusedforDell;public
6 | ciscoswitch;172.16.0.11;admin;MyPassword;cat65k.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;CATALYST_6500;onlyusedforDell;public
7 | ciscoswitch;172.16.0.11;admin;MyPassword;n5k.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;NEXUS_5K;onlyusedforDell;public
8 | ciscoswitch;172.16.0.11;admin;MyPassword;n7k.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;NEXUS_7K;onlyusedforDell;public
9 | ciscoswitch;172.16.0.11;admin;MyPassword;n9k.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;NEXUS_9K;onlyusedforDell;public
10 | aristaswitch;172.16.0.11;admin;MyPassword;arista.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;public
11 | dellswitch;172.16.0.11;admin;MyPassword;dellf10mlx10.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;FORCE_10_MXL_10;public
12 | dellswitch;172.16.0.11;admin;MyPassword;dellp8024.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;POWERCONNECT_8024;public
13 | dellswitch;172.16.0.11;admin;MyPassword;dell54048.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;S4048;public
14 | dellswitch;172.16.0.11;admin;MyPassword;dell29100.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;Z9100;public
15 | dellswitch;172.16.0.11;admin;MyPassword;dell56000.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;S6000;public
16 | brocadeswitch;172.16.0.11;admin;MyPassword;brocade.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;public
17 | juniperswitch;172.16.0.11;admin;MyPassword;juniper.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;public
18 | ciscoucs;172.16.0.11;admin;MyPassword;ucs.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;public
19 | hponeview;172.16.0.11;admin;MyPassword;hponeview.prod.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;
20 | hpvcmanager;172.16.0.11;admin;MyPassword;hpvc.lab.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;""
21 | checkpointfirewall;172.16.0.11;admin;MyPassword;checkpoint.prod.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;""
22 | panfirewall;172.16.0.11;admin;MyPassword;pan.prod.local;onlyusedforNSX;onlyusedforNSX;onlyusedforNSX;onlyusedforCisco;onlyusedforDell;""
--------------------------------------------------------------------------------
/examples/application-bulk-import.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Examples
2 | #
3 | # Example: Adding applications in bulk
4 | #
5 | # START Description
6 | # This script uses an input CSV (example: application-bulk-import.csv) to add multiple vRealize Network Insight
7 | # Applications. Modify application-bulk-import.csv to contain your applications and application tiers, along with
8 | # either the NSX Security Group or the VM names. Then run this script with the param -ApplicationsCSV to your CSV.
9 | # END Description
10 | #
11 | # Martijn Smit (@smitmartijn)
12 | # msmit@vmware.com
13 | # Version 1.0
14 |
15 | param (
16 | [parameter(Mandatory = $true, ValueFromPipeLine = $true, ValueFromPipeLineByPropertyName = $true)]
17 | [ValidateNotNullOrEmpty()]
18 | [string]$ApplicationsCSV
19 | )
20 |
21 | # Test CSV existance
22 | if (!(Test-Path $ApplicationsCSV)) {
23 | Write-Host "[$(Get-Date)] CSV with applications not found! ($ApplicationsCSV)" -ForegroundColor "red"
24 | Exit
25 | }
26 |
27 | # Cache for new application entity ids
28 | $new_apps = @{}
29 |
30 | # Read the CSV into memory (using delimiter ';' so you can use Excel to modify it)
31 | $csvList = Import-CSV $ApplicationsCSV -Delimiter ';'
32 | $csvLineNo = 0
33 | foreach ($csvLine in $csvList) {
34 | $csvLineNo += 1
35 |
36 | Write-Host "[$(Get-Date)] Processing application $($csvLine.Application).." -ForegroundColor "green"
37 |
38 | # First, see if the application exists (otherwise create it)
39 | if ($new_apps.ContainsKey($csvLine.Application)) {
40 | $application = $new_apps[$csvLine.Application]
41 | }
42 | else {
43 | $application = Get-vRNIApplication $csvLine.Application
44 | }
45 |
46 | if ($application -eq $null) {
47 | Write-Host "[$(Get-Date)] Application $($csvLine.Application) not found, so creating it.." -ForegroundColor "green"
48 | $application = New-vRNIApplication $csvLine.Application
49 | $new_apps.Add($csvLine.Application, $application)
50 | }
51 |
52 | # Format the filter
53 | $filters = @()
54 |
55 | # Is there a Security Group provided? If yes, get the entity id
56 | if ($csvLine."Security Group" -ne "") {
57 | $security_group_id = (Get-vRNISecurityGroup $csvLine."Security Group").entity_id
58 | if ($security_group_id -eq $null) {
59 | Write-Host "[$(Get-Date)] Wanted to use Security Group $($csvLine."Security Group"), but it doesn't exist - so skipping this rule!" -ForegroundColor "yellow"
60 | }
61 | else {
62 | $filters += "security_groups.entity_id = '$($security_group_id)'"
63 | }
64 | }
65 |
66 | # Are there VM Names provided? If yes, go through them and add them to the filter
67 | if ($csvLine."VM Names" -ne "") {
68 | $filter_vm = ""
69 | # Split VMs by comma and go through the list to add them to the filter string
70 | $vms = $csvLine."VM Names".Split(",")
71 | foreach ($vm in $vms) {
72 | $filter_vm += "name = '$($vm)' or "
73 | }
74 | # Remove last " or "
75 | $filter_vm = $filter_vm.Substring(0, $filter_vm.Length - 4)
76 | # Add it to the filter that will be passed to New-vRNIApplicationTier
77 | $filters += $filter_vm
78 | }
79 |
80 | # Make sure the filters aren't empty (non existing security group and no VM names provided), otherwise skip this tier
81 | if ($filters.Length -eq 0) {
82 | Write-Host "[$(Get-Date)] Skipping Tier '$($csvLine.Tier)' in application '$($csvLine.Application)' because filters are empty!" -ForegroundColor "red"
83 | Continue
84 | }
85 |
86 | # Add the tier!
87 | $tier = New-vRNIApplicationTier -Application $application -Name $csvLine.Tier -Filters $filters
88 | Write-Host "[$(Get-Date)] Added Tier '$($csvLine.Tier)' to application '$($csvLine.Application)' with filters: $($filters)" -ForegroundColor "green"
89 |
90 | # Sleep for a second, so we don't hit the API rate limiter
91 | Start-Sleep 1
92 | }
93 |
--------------------------------------------------------------------------------
/ChangeLog.md:
--------------------------------------------------------------------------------
1 | ## ChangeLog
2 |
3 | ### v6.5 - 2022-01-28
4 |
5 | @smitmartijn:
6 |
7 | - \[new] Match PowervRNI version to indicate support for vRNI versions
8 | - \[new] Support for NSXALB Data Source (NSX Advanced Load Balancer)
9 | - \[new] New message groups for the databus subscriber: flows, metrics, VMs, hosts, NICs, switchports
10 | - \[new] Get-vRNISDDCGroup
11 | - \[new] Get-vRNIVMCDirectConnect
12 | - \[new] Get-vRNIVMCDirectConnectInterface
13 | - \[new] Get-vRNISwitchPort
14 | - \[new] Get-vRNILogicalRouter
15 | - \[new] Get-vRNIVMwareTransitGateway
16 | - \[new] Get-vRNINSXTIPsecVPNSessions
17 | - \[new] Get-vRNISettingsLoginBanner
18 | - \[new] Set-vRNISettingsLoginBanner
19 | - \[new] Remove-vRNISettingsLoginBanner
20 |
21 | ### v2.0 - 2021-10-05
22 |
23 | @smitmartijn:
24 |
25 | - \[new] Connect-NIServer: Add support for vRNI Cloud locations by adding the -Location parameter
26 | - \[new] New-vRNIDataSource: Add support for Cisco ASR and ISR models (types: CISCOASRISR, CISCOASR1000, CISCOISR4000)
27 | - \[new] Get-vRNISDDC: New cmdlet to retrieve SDDC objects
28 | - \[new] Get-vRNIDatabusSubscriber: New cmdlet to retrieve all databus subscribers
29 | - \[new] New-vRNIDatabusSubscriber: New cmdlet to create a databus subscriber
30 | - \[new] Remove-vRNIDatabusSubscriber: New cmdlet to remove a databus subscriber
31 |
32 | ### v1.9 - 2021-07-09
33 |
34 | @smitmartijn:
35 |
36 | - \[new] Add cmdlet Update-vRNIDataSource to update data source details (credentials, nickname, notes)
37 | - \[new] Add cmdlet Invoke-vRNISearch to run search queries. Example: Invoke-vRNISearch -Query “VM where CPU Count > 2”
38 | - \[new] Add data source support for: AWS, Mellanox, Cisco ASR/XR, VMware HCX, HPE Switches
39 | - \[new] Add support for Custom polling intervals
40 | - \[new] Add support for Enabling IPFIX on vCenter VDS when adding
41 | - \[new] Add support for Platform Backup Management. New cmdlets: Get-vRNIBackup, Get-vRNIBackupStatus, Remove-vRNIBackup, Enable-vRNIBackup, Disable-vRNIBackup, Set-vRNIBackup
42 | - \[new] Add support for License Management. New cmdlets: Get-vRNILicensing, Test-vRNILicensing, Install-vRNILicensing, Remove-vRNILicensing
43 |
44 | ### v1.4 - 2018-10-13
45 |
46 | @smitmartijn:
47 |
48 | - \[new] Add cmdlet Get-vRNIRecommendedRulesNsxBundle to download a zip file with the recommended firewall rules which can be used by the Importer Tool to send the firewall rules to NSX
49 | - \[bug-fix] Fix a random connection issue to on-prem vRNI by fixing the on-prem vs SaaS detection
50 |
51 | ### v1.3
52 |
53 | @smitmartijn:
54 |
55 | - \[new] Add Connect-NIServer to connect to the Network Insight as a Service on the VMware Cloud Services.
56 |
57 | ### v1.2
58 |
59 | @smitmartijn:
60 |
61 | - \[new] Add Get-vRNIDataSourceSNMPConfig and Set-vRNIDataSourceSNMPConfig to retrieve and configure SNMP settings for certain data sources
62 | - \[fix] Fixed New-vRNIDataSource when using a Cisco or Dell switch type (it didn't add the required switch type API value)
63 |
64 | ### v1.1
65 |
66 | @smitmartijn:
67 |
68 | - \[new] Execute Get-vRNIAPIVersion when using Connect-vRNIServer and store API version for further use
69 | - \[new] Use the /entities/fetch endpoint when API v1.1.0 is available to significantly speed up entity results
70 | - \[new] Use the /groups/applications/fetch endpoint when API v1.1.0 is available to significantly speed up application results (5500% faster on 400 applications)
71 | - \[enhancement] Use the /search endpoint when looking for a single entity (not just VMs), speeding up the execution time
72 | - \[enhancement] Make sure Invoke-vRNIRestMethod takes a 100ms break before running to prevent API throttling (error 429)
73 |
74 | @awickham10:
75 |
76 | - \[enhancement] Use /search endpoint when looking for a single VM, speeding up the execution time
77 |
78 | @mtboren:
79 | - \[enhancement] Added a bit to some ErrorMessage output in `Invoke-vRNIRestMethod`, and updated to throw actual `ErrorRecord` object in catch situation (to enable deeper debugging by user)
80 | - \[bugfix] Updated remaining functions that take value from pipeline to handle multiple objects from pipeline (`Remove-vRNIApplication`, `New-vRNIApplicationTier`, `Remove-vRNIApplicationTier`, `Disable-vRNIDataSource`, `Enable-vRNIDataSource`, `Remove-vRNIDataSource`)
81 |
82 |
--------------------------------------------------------------------------------
/publish/Include.ps1:
--------------------------------------------------------------------------------
1 | #
2 | # This file is used by Publish.ps1 to generate the manifest and publish PowervRNI
3 | # to the PowerShell Gallery.
4 | #
5 | # Add any new cmdlets in this file, otherwise they won't get published in the module
6 | #
7 |
8 | # This is the version of PowervRNI. The publish script will also append ".build number",
9 | # put this in a "major.minor" format
10 | $PowervRNI_Version = "6.51"
11 |
12 | $FunctionsToExport = @(
13 | 'Connect-vRNIServer',
14 | 'Connect-NIServer',
15 | 'Disable-vRNIDataSource',
16 | 'Disconnect-vRNIServer',
17 | 'Enable-vRNIDataSource',
18 | 'Get-vRNIAPIVersion',
19 | 'Get-vRNIApplication',
20 | 'Get-vRNIApplicationTier',
21 | 'Get-vRNIDataSource',
22 | 'Get-vRNIDatastore',
23 | 'Get-vRNIDistributedSwitch',
24 | 'Get-vRNIDistributedSwitchPortGroup',
25 | 'Get-vRNIEntity',
26 | 'Get-vRNIEntityName',
27 | 'Get-vRNIFirewallRule',
28 | 'Get-vRNIFlow',
29 | 'Get-vRNIHost',
30 | 'Get-vRNIHostVMKNic',
31 | 'Get-vRNIIPSet',
32 | 'Get-vRNIL2Network',
33 | 'Get-vRNINodes',
34 | 'Get-vRNINSXManager',
35 | 'Get-vRNIProblem',
36 | 'Get-vRNIRecommendedRules',
37 | 'Get-vRNIRecommendedRulesNsxBundle',
38 | 'Get-vRNISecurityGroup',
39 | 'Get-vRNISecurityTag',
40 | 'Get-vRNIService',
41 | 'Get-vRNIServiceGroup',
42 | 'Get-vRNIvCenter',
43 | 'Get-vRNIvCenterCluster',
44 | 'Get-vRNIvCenterDatacenter',
45 | 'Get-vRNIvCenterFolder',
46 | 'Get-vRNIVM',
47 | 'Get-vRNIVMvNIC',
48 | 'Get-vRNIDataSourceSNMPConfig',
49 | 'Get-vRNISDDC',
50 | 'Invoke-vRNIRestMethod',
51 | 'New-vRNIApplication',
52 | 'New-vRNIApplicationTier',
53 | 'New-vRNIDataSource',
54 | 'Remove-vRNIApplication',
55 | 'Remove-vRNIApplicationTier',
56 | 'Remove-vRNIDataSource',
57 | 'Set-vRNIDataSourceSNMPConfig',
58 | 'New-vRNISubnetMapping',
59 | 'Get-vRNISubnetMapping',
60 | 'Get-vRNIEastWestIP',
61 | 'Add-vRNIEastWestIP',
62 | 'Remove-vRNIEastWestIP',
63 | 'Get-vRNINorthSouthIP',
64 | 'Add-vRNINorthSouthIP',
65 | 'Remove-vRNINorthSouthIP',
66 | 'Get-vRNISettingsVIDM',
67 | 'Set-vRNISettingsVIDM',
68 | 'Get-vRNISettingsUserGroup',
69 | 'Set-vRNISettingsUserGroup',
70 | 'Remove-vRNISettingsUserGroup',
71 | 'Get-vRNISettingsUser',
72 | 'Set-vRNISettingsUser',
73 | 'Remove-vRNISettingsUser',
74 | 'Get-vRNIAuditLogs',
75 | 'Get-vRNIApplicationMemberVM',
76 | 'Set-vRNIUserPassword',
77 | 'Get-vRNIKubernetesServices',
78 | 'Update-vRNIDataSourceData',
79 | 'Update-vRNINSXvControllerClusterPassword',
80 | 'Get-vRNIEntityNames',
81 | 'Invoke-vRNISearch',
82 | 'Get-vRNILicensing',
83 | 'Test-vRNILicensing',
84 | 'Install-vRNILicensing',
85 | 'Remove-vRNILicensing',
86 | 'Get-vRNIBackup',
87 | 'Get-vRNIBackupStatus',
88 | 'Remove-vRNIBackup',
89 | 'Enable-vRNIBackup',
90 | 'Disable-vRNIBackup',
91 | 'Set-vRNIBackup',
92 | 'Get-vRNIDatabusSubscriber',
93 | 'New-vRNIDatabusSubscriber',
94 | 'Remove-vRNIDatabusSubscriber',
95 | 'Get-vRNISDDCGroup',
96 | 'Get-vRNIVMCDirectConnect',
97 | 'Get-vRNIVMCDirectConnectInterface',
98 | 'Get-vRNISwitchPort',
99 | 'Get-vRNILogicalRouter',
100 | 'Get-vRNIVMwareTransitGateway',
101 | 'Get-vRNINSXTIPsecVPNSessions',
102 | 'Get-vRNISettingsLoginBanner',
103 | 'Set-vRNISettingsLoginBanner',
104 | 'Remove-vRNISettingsLoginBanner'
105 | )
106 |
107 | # Manifest settings
108 | $Manifest_Common = @{
109 | RootModule = 'PowervRNI.psm1'
110 | GUID = 'a34be6be-3dc1-457a-aea3-d4263481ed79'
111 | Author = 'Martijn Smit'
112 | CompanyName = 'VMware'
113 | Copyright = 'Copyright 2022 VMware. All rights reserved.'
114 | Description = 'A PowerShell module to talk to the vRealize Network Insight API'
115 | DotNetFrameworkVersion = '4.0'
116 | FunctionsToExport = $FunctionsToExport
117 | CmdletsToExport = '*'
118 | VariablesToExport = '*'
119 | AliasesToExport = '*'
120 | LicenseUri = 'https://github.com/PowervRNI/powervrni/blob/master/LICENSE.md'
121 | ProjectUri = 'https://github.com/PowervRNI/powervrni'
122 | ReleaseNotes = '### v6.5.1 - 2022-03-07
123 | - \[fixed] Change the application page size to 100 to fix seeing an error about a hard limit in vRNI 6.5.1'
124 | }
125 |
--------------------------------------------------------------------------------
/examples/cmdb-import-from-itop.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Examples
2 | #
3 | # Example: Import Applications from iTop
4 | #
5 | # START Description
6 | # Retrieves applications from the CMDB iTop, and imports them into vRNI.
7 | # END Description
8 | #
9 | # Martijn Smit (@smitmartijn)
10 | # msmit@vmware.com
11 | # Version 1.0
12 |
13 | $CONFIG_URL = "http://itop.lab/webservices/rest.php?version=1.3"
14 | $CONFIG_USER = "api"
15 | $CONFIG_PASS = "VMware1!"
16 | $CONFIG_VRNI_HOST = "network-insight.platform.lab"
17 | $CONFIG_VRNI_USER = "admin@local"
18 | $CONFIG_VRNI_PASS = "VMware1!"
19 |
20 | $vrni_connection = Connect-vRNIServer -Server $CONFIG_VRNI_HOST -User $CONFIG_VRNI_USER -Password ($CONFIG_VRNI_PASS | ConvertTo-SecureString -AsPlainText -Force)
21 | Write-Host -ForegroundColor 'Green' "Connected to Network Insight with PowervRNI!"
22 | Write-Host "Connecting to CMDB to get a list of applications..."
23 |
24 | # Select all applications from the iTop API
25 | $app_request_json = @{
26 | 'operation' = 'core/get' ;
27 | 'class' = 'ApplicationSolution' ;
28 | 'key' = "SELECT ApplicationSolution" ;
29 | 'output_fields' = '*'
30 | } | ConvertTo-Json
31 |
32 | # Format the POST payload
33 | $postParams = @{
34 | auth_user = $CONFIG_USER;
35 | auth_pwd = $CONFIG_PASS;
36 | json_data = $app_request_json;
37 | }
38 |
39 | # Execute web request and translate the incoming result to a PowerShell object
40 | $res = Invoke-WebRequest -Uri $CONFIG_URL -Method POST -Body $postParams -UseBasicParsing
41 | # The actual content is hidden is key 'Content' (surprise!)
42 | $json = ConvertFrom-Json $res.Content
43 |
44 | # Go through all applications
45 | foreach ($info in $json.objects.PSObject.Properties) {
46 | $appName = $info.Value.fields.name
47 | Write-Host -ForegroundColor 'Magenta' "Found Application: $($appName)"
48 | $fields = $info.Value
49 |
50 | # First, see if the application exists (otherwise create it)
51 | $application = Get-vRNIApplication -Name $appName -Connection $vrni_connection
52 |
53 | # Application doesn't exist in vRNI, create it
54 | if ($null -eq $application) {
55 | Write-Host "Application $($appName) not found in Network Insight, so creating it.." -ForegroundColor "Yellow"
56 | $application = New-vRNIApplication -Name $appName
57 | Write-Host "Application $($appName) created!" -ForegroundColor "Green"
58 | }
59 |
60 | # Array for holding the tier/VM combo
61 | $appTiers = @{}
62 |
63 | Write-Host "Looking for VMs attached to this application..."
64 | # This is only going to supply us with the VM name and ID
65 | foreach ($field in $info.Value.fields.functionalcis_list) {
66 | Write-Host -ForegroundColor 'Magenta' "Found a VM attached to $($appName): "
67 | #Write-Host "VM: $($field.functionalci_name)"
68 |
69 | # ..so we need to request more details around this VM.
70 | $vm_request_json = @{
71 | 'operation' = 'core/get' ;
72 | 'class' = 'VirtualMachine' ;
73 | 'key' = "SELECT VirtualMachine WHERE id = $($field.functionalci_id)" ;
74 | 'output_fields' = '*'
75 | } | ConvertTo-Json
76 |
77 | $postParams = @{
78 | auth_user = $CONFIG_USER;
79 | auth_pwd = $CONFIG_PASS;
80 | json_data = $vm_request_json
81 | }
82 | # Execute the VM info request and translate the output to
83 | $res = Invoke-WebRequest -Uri $CONFIG_URL -Method POST -Body $postParams -UseBasicParsing
84 |
85 | $json = ConvertFrom-Json $res.Content
86 | foreach ($info in $json.objects.PSObject.Properties) {
87 | $fields = $info.Value
88 | $tier = $($fields.fields.description)
89 |
90 | if ($null -eq $appTiers.$tier) {
91 | $appTiers.$tier = @()
92 | }
93 | $appTiers.$tier += $fields.fields.name
94 | Write-Host "VM: $($fields.fields.name) - Tier: $($tier)"
95 | #Write-Host "OS: $($fields.fields.osfamily_name) - $($fields.fields.osversion_name)"
96 | #Write-Host "IP Address: $($fields.fields.managementip)"
97 | }
98 | }
99 |
100 | Write-Host "Adding tiers and VMs to Network Insight.."
101 |
102 | foreach ($tier in $appTiers.Keys) {
103 | $filters = @()
104 | $filter_vm = ""
105 | foreach ($vm in $appTiers.$tier) {
106 | $filter_vm += "name = '$($vm)' or "
107 | }
108 | $filter_vm = $filter_vm.Substring(0, $filter_vm.Length - 4)
109 | $filters += $filter_vm
110 |
111 | $vrni_tier = New-vRNIApplicationTier -Application $application -Name $tier -Filters $filters
112 | Write-Host "Added Tier '$($tier)' to application '$($appname)' to Network Insight!" -ForegroundColor "green"
113 |
114 | }
115 | }
116 |
117 | Write-Host "All done."
118 |
--------------------------------------------------------------------------------
/examples/archive-flows-to-vrli/vrealize-log-insight.ps1:
--------------------------------------------------------------------------------
1 |
2 |
3 | function Send-vRLIMessage
4 | {
5 | <#
6 | .SYNOPSIS
7 | Sends a message to vRealize Log Insight over the CFAPI. Allows usage of fields (tags).
8 |
9 | .EXAMPLE
10 | PS C:\> Send-vRLIMessage -Server vrli.lab.local -Message "testing powershell function!"
11 |
12 | Sends a plain message
13 |
14 | .EXAMPLE
15 | PS C:\> Send-vRLIMessage -Server vrli.lab.local -Message "testing powershell function!" -Fields @{ tag1 = "value1"; tag2 = "value2"; }
16 |
17 | Sends a message, including fields/tags and their values
18 | #>
19 |
20 | param (
21 | # Destination vRLI server that message is to be sent to.
22 | [Parameter(Mandatory = $true)]
23 | [ValidateNotNullOrEmpty()]
24 | [String]
25 | $Server,
26 | # Destination vRLI server port that message is to be sent to. Defaults to 9543
27 | [Parameter(Mandatory = $false)]
28 | [ValidateNotNullOrEmpty()]
29 | [Int]
30 | $Port = 9543,
31 | # Log/event message
32 | [Parameter(Mandatory = $true)]
33 | [ValidateNotNullOrEmpty()]
34 | [String]
35 | $Message,
36 | # Timestamp of the message. Defaults to current time.
37 | [Parameter(Mandatory = $false)]
38 | [ValidateNotNullOrEmpty()]
39 | [Int]
40 | $Timestamp = [DateTimeOffset]::Now.ToUnixTimeSeconds(),
41 | # Log/event message
42 | [Parameter(Mandatory = $false)]
43 | [ValidateNotNullOrEmpty()]
44 | [hashtable]
45 | $Fields = @{}
46 | )
47 |
48 |
49 | # Build the vRLI URL
50 | $URL = "https://$($Server):$($Port)/api/v1/events/ingest/0"
51 |
52 | # Build the event message that will be passed to vRLI
53 | $event = @{
54 | text = $Message
55 | timestamp = $Timestamp
56 | }
57 |
58 | # Iterate through the provides fields, if any are given
59 | if($Fields)
60 | {
61 | $event.fields = @()
62 | foreach($field_name in $Fields.keys)
63 | {
64 | # Build a temporary array that can be added to the fields value.
65 | $field_tmp = @{
66 | name = $field_name
67 | content = $Fields[$field_name]
68 | }
69 | $event.fields += $field_tmp
70 | }
71 | }
72 |
73 | # Build the request body. The API call supports multiple messages/events at the same time, that's why it's a list.
74 | $requestBody = @{
75 | events = @( $event )
76 | }
77 | $jsonBody = $requestBody | ConvertTo-Json -Depth 4
78 |
79 | Write-Debug "$(Get-Date -format s) Sent JSON: $($jsonBody)"
80 |
81 | # Energize!
82 | try
83 | {
84 | $response = Invoke-RestMethod $URL -Method POST -Body $jsonBody -ContentType 'application/json'
85 | }
86 | # If its a webexception, we may have got a response from the server with more information...
87 | # Even if this happens on PoSH Core though, the ex is not a webexception and we cant get this info :(
88 | catch [System.Net.WebException] {
89 | #Check if there is a response populated in the response prop as we can return better detail.
90 | $response = $_.exception.response
91 | if ( $response ) {
92 | $responseStream = $response.GetResponseStream()
93 | $reader = New-Object system.io.streamreader($responseStream)
94 | $responseBody = $reader.readtoend()
95 | ## include ErrorDetails content in case therein lies juicy info
96 | $ErrorString = "$($MyInvocation.MyCommand.Name) : The API response received indicates a failure. $($response.StatusCode.value__) : $($response.StatusDescription) : Response Body: $($responseBody)`nErrorDetails: '$($_.ErrorDetails)'"
97 |
98 | # Log the error with response detail.
99 | Write-Warning -Message $ErrorString
100 | ## throw the actual error, so that the consumer can debug via the actuall ErrorRecord
101 | Throw $_
102 | }
103 | else
104 | {
105 | # No response, log and throw the underlying ex
106 | $ErrorString = "$($MyInvocation.MyCommand.Name) : Exception occured calling invoke-restmethod. $($_.exception.tostring())"
107 | Write-Warning -Message $_.exception.tostring()
108 | ## throw the actual error, so that the consumer can debug via the actuall ErrorRecord
109 | Throw $_
110 | }
111 | }
112 | catch {
113 | # Not a webexception (may be on PoSH core), log and throw the underlying ex string
114 | $ErrorString = "$($MyInvocation.MyCommand.Name) : Exception occured calling invoke-restmethod. $($_.exception.tostring())"
115 | Write-Warning -Message $ErrorString
116 | ## throw the actual error, so that the consumer can debug via the actuall ErrorRecord
117 | Throw $_
118 | }
119 |
120 | Write-Debug "$(Get-Date -format s) Invoke-RestMethod Result: $response"
121 |
122 | # Return result
123 | if($response) { $response }
124 | }
125 |
--------------------------------------------------------------------------------
/examples/datasource-bulk-import.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Examples
2 | #
3 | # Example: Adding datasources in bulk
4 | #
5 | # START Description
6 | # This script uses an input CSV (example: datasource-bulk-import.csv) to add multiple vRealize Network Insight
7 | # Data Sources. Modify datasource-bulk-import.csv to contain your own data sources (vCenters, NSX, switches, firewalls)
8 | # and run this script with the param -DatasourcesCSV to your CSV.
9 | # END Description
10 | #
11 | # More info: https://lostdomain.org/2018/11/19/integrating-servicenow-with-network-insight/
12 | #
13 | # Martijn Smit (@smitmartijn)
14 | # msmit@vmware.com
15 | # Version 1.0
16 |
17 |
18 | param (
19 | [parameter(Mandatory = $true, ValueFromPipeLine = $true, ValueFromPipeLineByPropertyName = $true)]
20 | [ValidateNotNullOrEmpty()]
21 | [string]$DatasourcesCSV
22 | )
23 |
24 | # Test CSV existance
25 | if (!(Test-Path $DatasourcesCSV)) {
26 | Write-Host "[$(Get-Date)] CSV with data sources not found! ($DatasourcesCSV)" -ForegroundColor "red"
27 | Exit
28 | }
29 |
30 | # Look up collector ID. This assumes you only have 1 collector in play
31 | $collectorId = (Get-vRNINodes | Where { $_.node_type -eq "PROXY_VM" } | Select -ExpandProperty id)
32 |
33 | # Read the CSV into memory (using delimiter ';' so you can use Excel to modify it)
34 | $csvList = Import-CSV $DatasourcesCSV -Delimiter ';'
35 | $csvLineNo = 0
36 | foreach ($csvLine in $csvList) {
37 | $csvLineNo += 1
38 |
39 | Write-Host "[$(Get-Date)] Adding a $($csvLine.DatasourceType) Data Source with IP $($csvLine.IP).." -ForegroundColor "green"
40 |
41 | # Build up the params we're going to give to New-vRNIDataSource
42 | $cmdParams = @{
43 | "DataSourceType" = $csvLine.DatasourceType;
44 | "Username" = $csvLine.Username;
45 | "Password" = ($csvLine.Password | ConvertTo-SecureString -AsPlainText -Force);
46 | "IP" = $csvLine.IP;
47 | "Nickname" = $csvLine.Nickname;
48 | "CollectorVMId" = $collectorId;
49 | }
50 |
51 | # sort out NSX-V specific parameters
52 | if ($csvLine.DatasourceType -eq "nsxv") {
53 | if ($csvLine.NSX_ENABLE_CENTRAL_CLI -eq "TRUE") {
54 | $cmdParams.Add("NSXEnableCentralCLI", $True)
55 | }
56 | else {
57 | $cmdParams.Add("NSXEnableCentralCLI", $False)
58 | }
59 | if ($csvLine.NSX_ENABLE_IPFIX -eq "TRUE") {
60 | $cmdParams.Add("NSXEnableIPFIX", $True)
61 | }
62 | else {
63 | $cmdParams.Add("NSXEnableIPFIX", $False)
64 | }
65 |
66 | # Retrieve the vCenter Entity ID by doing a lookup with it's nickname
67 | $vcId = (Get-vRNIDataSource | Where { $_.nickname -eq $csvLine.NSX_VCENTER_NICKNAME } | Select -ExpandProperty entity_id)
68 | $cmdParams.Add("NSXvCenterID", $vcId)
69 | }
70 |
71 | # add a -CiscoSwitchType param when the datasource type is a cisco switch
72 | if ($csvLine.DatasourceType -eq "ciscoswitch") {
73 | # Sanity check on the input
74 | if (($csvLine.CISCO_SWITCHTYPE -eq "CATALYST_3000") -Or
75 | ($csvLine.CISCO_SWITCHTYPE -eq "CATALYST_4500") -Or
76 | ($csvLine.CISCO_SWITCHTYPE -eq "CATALYST_6500") -Or
77 | ($csvLine.CISCO_SWITCHTYPE -eq "NEXUS_5K") -Or
78 | ($csvLine.CISCO_SWITCHTYPE -eq "NEXUS_7K") -Or
79 | ($csvLine.CISCO_SWITCHTYPE -eq "NEXUS_9K")) {
80 | $cmdParams.Add("CiscoSwitchType", $csvLine.CISCO_SWITCHTYPE)
81 | }
82 | else {
83 | Write-Host "[$(Get-Date)] Invalid CISCO_SWITCHTYPE ($($csvLine.CISCO_SWITCHTYPE)) given on line $($csvLineNo), skipping.." -ForegroundColor "yellow"
84 | }
85 | }
86 |
87 | # add a -DellSwitchType param when the datasource type is a dell switch
88 | if ($csvLine.DatasourceType -eq "dellswitch") {
89 | # Sanity check on the input
90 | if (($csvLine.DELL_SWITCHTYPE -eq "FORCE_10_MXL_10") -Or
91 | ($csvLine.DELL_SWITCHTYPE -eq "POWERCONNECT_8024") -Or
92 | ($csvLine.DELL_SWITCHTYPE -eq "S4048") -Or
93 | ($csvLine.DELL_SWITCHTYPE -eq "Z9100") -Or
94 | ($csvLine.DELL_SWITCHTYPE -eq "S6000")) {
95 | $cmdParams.Add("DellSwitchType", $csvLine.DELL_SWITCHTYPE)
96 | }
97 | else {
98 | Write-Host "[$(Get-Date)] Invalid DELL_SWITCHTYPE ($($csvLine.DELL_SWITCHTYPE)) given on line $($csvLineNo), skipping.." -ForegroundColor "yellow"
99 | }
100 | }
101 |
102 | # Execute!
103 | try {
104 | $newDs = New-vRNIDataSource @cmdParams
105 | }
106 | catch {
107 | # If 1 data source addition fails because the data source itself times out or is unavailable, make a note and move on to the next data source
108 | Write-Host "[$(Get-Date)] Unable to add data source with parameters:" -ForegroundColor "red"
109 | $cmdParams
110 | Write-Host "[$(Get-Date)] Exception:" -ForegroundColor "red"
111 | $_.Exception
112 | # Don't even bother with SNMP, continue to the next data source
113 | continue
114 | }
115 |
116 |
117 | # Set SNMP community after adding - just SNMP v2c support right now
118 | if ($csvLine.SnmpCommunity -ne "" -And ($csvLine.DataSourceType -eq "ciscoswitch" -Or $csvLine.DataSourceType -eq "aristaswitch" -Or $csvLine.DataSourceType -eq "dellos10switch" -Or $csvLine.DataSourceType -eq "ciscoucs")) {
119 | try {
120 | ($newDs | Set-vRNIDataSourceSNMPConfig -Enabled $true -Community $csvLine.SnmpCommunity | Out-Null)
121 | }
122 | catch {
123 | Write-Host "Unable to add snmp config to:"
124 | $newDs
125 | Write-Host "Exception:"
126 | $_.Exception
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PowervRNI
2 |
3 | *A PowerShell module for vRealize Network Insight*
4 |
5 | Starting vRealize Network Insight (vRNI) 3.6, the platform has a public API. PowervRNI is a PowerShell module that takes advantage of those public APIs and provides you with the option to look at vRNI data using PowerShell.
6 |
7 |
8 | This module is _not supported_ by VMware, and comes with no warranties express or implied. Please test and validate its functionality before using this product in a production environment.
9 |
10 | ## Installing PowervRNI
11 |
12 |
13 | There are 2 ways of installing PowervRNI. An easy one through PowerShell Gallery where everything is taken care of for you, or a slightly harder one where you download the module and load it up manually.
14 |
15 | ### PowerShell Gallery
16 |
17 | ```
18 | PS C:\> Install-Module PowervRNI
19 | PS C:\> Import-Module PowervRNI
20 | ```
21 |
22 | That's it, you're off the the races.
23 |
24 | ### Manual Download
25 |
26 | Right now, PowervRNI is a simple two-file module. To install it, download it to a PowerShell enabled machine and load it. PowervRNI is supported for PowerShell Desktop & Core, so Windows, MacOS and Linux. Here is an example on how to load it:
27 |
28 | ```
29 | PS C:\> Invoke-WebRequest -Uri "https://raw.githubusercontent.com/powervrni/powervrni/master/PowervRNI.psm1" -OutFile "PowervRNI.psm1"
30 | PS C:\> Invoke-WebRequest -Uri "https://raw.githubusercontent.com/powervrni/powervrni/master/PowervRNI.psd1" -OutFile "PowervRNI.psd1"
31 | PS C:\> Import-Module .\PowervRNI.psd1
32 | ```
33 |
34 | ## Usage
35 |
36 | A more elaborate usage guide will follow, but here's a quick example on how to get started.
37 |
38 | ### Connecting to the vRNI Platform VM
39 |
40 | The API of vRNI requires you to login to the Platform VM first. Here's how:
41 |
42 | ```
43 | PS C:\> $creds = Get-Credential
44 | PS C:\> Connect-vRNIServer -Server vrni-platform.lab -Credential $creds
45 | ```
46 |
47 | or, if you'd like the system to ask you for your credentials
48 |
49 | ```
50 | PS C:\> Connect-vRNIServer -Server vrni-platform.lab
51 | ```
52 |
53 | ### Connecting to vRNI Cloud
54 |
55 | If you're using vRNI Cloud, use `Connect-NIServer` to authenticate. First, generate a [CSP Refresh Token](https://docs.vmware.com/en/VMware-Cloud-services/services/Using-VMware-Cloud-Services/GUID-E2A3B1C1-E9AD-4B00-A6B6-88D31FCDDF7C.html).
56 |
57 | ```
58 | PS C:\> Connect-NIServer -RefreshToken xxx-xxx-xxx-xxx -Location UK
59 | ```
60 |
61 | Use the `-Location` parameter to indicate where the vRNI Cloud service is hosted. A list of regions can be found using `Get-Help Connect-NIServer -Examples`
62 |
63 | ### Getting Started
64 |
65 | After logging in and starting a session, you can start doing information calls to vRNI. To see what kind of cmdlets PowervRNI offers and what information you can get out of vRNI with it, use the following command:
66 |
67 | ```
68 | PS C:\> Get-Command -Module PowervRNI ```
69 | ```
70 |
71 | You'll see that there are a bunch of cmdlets you can use. To give you an example of what kind of output PowervRNI produces, here's an example from my lab:
72 |
73 | ```
74 | PS C:\> Get-vRNIHost
75 |
76 | entity_id : 14207:4:204319385
77 | name : esxi03.lab
78 | entity_type : Host
79 | vmknics : {@{entity_id=14307:17:1822450329; entity_type=Vmknic}, @{entity_id=14307:17:1827250360; entity_type=Vmknic}, @{entity_id=14307:17:1827250298; entity_type=Vmknic}}
80 | cluster : @{entity_id=14307:66:1217795335; entity_type=Cluster}
81 | vcenter_manager : @{entity_id=14307:8:5696601749271539863; entity_type=VCenterManager}
82 | vm_count : 20
83 | datastores : {@{entity_id=14307:80:1083140774; entity_type=Datastore}, @{entity_id=14307:80:1082389334; entity_type=Datastore}, @{entity_id=14307:80:1860142552; entity_type=Datastore}}
84 | service_tag :
85 | vendor_id : host-2921
86 | nsx_manager : @{entity_id=14307:7:1483719682; entity_type=NSXVManager}
87 | maintenance_mode : NOTINMAINTENANCEMODE
88 | connection_state : CONNECTED
89 |
90 | entity_id : 14307:4:1142332887
91 | ```
92 |
93 | More examples are available in the examples/ directory and [here](https://lostdomain.org/tag/powervrni/)
94 |
95 |
96 | ## Contact
97 |
98 | Currently, [@smitmartijn](https://twitter.com/smitmartijn) started this project and will keep maintaining it. Reach out to me via twitter or the [Issues Page](https://github.com/powervrni/powervrni/issues) here on GitHub. If you want to contribute, also get in touch with me.
99 |
100 |
101 | ## Is PowervRNI supported by VMware?
102 |
103 | No. This is an opensource project started by [@smitmartijn](https://twitter.com/smitmartijn) and not supported by VMware. Please test and validate its functionality before using in a production environment.
104 |
105 |
106 | ## License
107 |
108 | PowervRNI is licensed under GPL v2.
109 |
110 | This program is free software: you can redistribute it and/or modify it under
111 | the terms of the GNU General Public License version 2, as published by the Free Software Foundation.
112 |
113 | This program is distributed in the hope that it will be useful, but WITHOUT ANY
114 | WARRANTY; without even the implied warranty of MERCHANTIBILITY or FITNESS
115 | FOR A PARTICULAR PURPOSE. See the GNU General Public License version 2 for more details.
116 |
117 | You should have received a copy of the General Public License version 2 along with this program.
118 | If not, see https://www.gnu.org/licenses/gpl-2.0.html.
119 |
120 | The full text of the General Public License 2.0 is provided in the COPYING file.
121 | Some files may be comprised of various open source software components, each of which
122 | has its own license that is located in the source code of the respective component.
--------------------------------------------------------------------------------
/PowervRNI.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'PowervRNI'
3 | #
4 | # Generated by: Martijn Smit
5 | #
6 | # Generated on: 3/7/2022
7 | #
8 |
9 | @{
10 |
11 | # Script module or binary module file associated with this manifest.
12 | RootModule = 'PowervRNI.psm1'
13 |
14 | # Version number of this module.
15 | ModuleVersion = '6.51.185'
16 |
17 | # Supported PSEditions
18 | # CompatiblePSEditions = @()
19 |
20 | # ID used to uniquely identify this module
21 | GUID = 'a34be6be-3dc1-457a-aea3-d4263481ed79'
22 |
23 | # Author of this module
24 | Author = 'Martijn Smit'
25 |
26 | # Company or vendor of this module
27 | CompanyName = 'VMware'
28 |
29 | # Copyright statement for this module
30 | Copyright = 'Copyright 2022 VMware. All rights reserved.'
31 |
32 | # Description of the functionality provided by this module
33 | Description = 'A PowerShell module to talk to the vRealize Network Insight API'
34 |
35 | # Minimum version of the PowerShell engine required by this module
36 | PowerShellVersion = '6.0'
37 |
38 | # Name of the PowerShell host required by this module
39 | # PowerShellHostName = ''
40 |
41 | # Minimum version of the PowerShell host required by this module
42 | # PowerShellHostVersion = ''
43 |
44 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
45 | DotNetFrameworkVersion = '4.0'
46 |
47 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
48 | # ClrVersion = ''
49 |
50 | # Processor architecture (None, X86, Amd64) required by this module
51 | # ProcessorArchitecture = ''
52 |
53 | # Modules that must be imported into the global environment prior to importing this module
54 | # RequiredModules = @()
55 |
56 | # Assemblies that must be loaded prior to importing this module
57 | # RequiredAssemblies = @()
58 |
59 | # Script files (.ps1) that are run in the caller's environment prior to importing this module.
60 | # ScriptsToProcess = @()
61 |
62 | # Type files (.ps1xml) to be loaded when importing this module
63 | # TypesToProcess = @()
64 |
65 | # Format files (.ps1xml) to be loaded when importing this module
66 | # FormatsToProcess = @()
67 |
68 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
69 | # NestedModules = @()
70 |
71 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
72 | FunctionsToExport = 'Connect-vRNIServer', 'Connect-NIServer', 'Disable-vRNIDataSource',
73 | 'Disconnect-vRNIServer', 'Enable-vRNIDataSource',
74 | 'Get-vRNIAPIVersion', 'Get-vRNIApplication',
75 | 'Get-vRNIApplicationTier', 'Get-vRNIDataSource', 'Get-vRNIDatastore',
76 | 'Get-vRNIDistributedSwitch', 'Get-vRNIDistributedSwitchPortGroup',
77 | 'Get-vRNIEntity', 'Get-vRNIEntityName', 'Get-vRNIFirewallRule',
78 | 'Get-vRNIFlow', 'Get-vRNIHost', 'Get-vRNIHostVMKNic', 'Get-vRNIIPSet',
79 | 'Get-vRNIL2Network', 'Get-vRNINodes', 'Get-vRNINSXManager',
80 | 'Get-vRNIProblem', 'Get-vRNIRecommendedRules',
81 | 'Get-vRNIRecommendedRulesNsxBundle', 'Get-vRNISecurityGroup',
82 | 'Get-vRNISecurityTag', 'Get-vRNIService', 'Get-vRNIServiceGroup',
83 | 'Get-vRNIvCenter', 'Get-vRNIvCenterCluster',
84 | 'Get-vRNIvCenterDatacenter', 'Get-vRNIvCenterFolder', 'Get-vRNIVM',
85 | 'Get-vRNIVMvNIC', 'Get-vRNIDataSourceSNMPConfig', 'Get-vRNISDDC',
86 | 'Invoke-vRNIRestMethod', 'New-vRNIApplication',
87 | 'New-vRNIApplicationTier', 'New-vRNIDataSource',
88 | 'Remove-vRNIApplication', 'Remove-vRNIApplicationTier',
89 | 'Remove-vRNIDataSource', 'Set-vRNIDataSourceSNMPConfig',
90 | 'New-vRNISubnetMapping', 'Get-vRNISubnetMapping',
91 | 'Get-vRNIEastWestIP', 'Add-vRNIEastWestIP', 'Remove-vRNIEastWestIP',
92 | 'Get-vRNINorthSouthIP', 'Add-vRNINorthSouthIP',
93 | 'Remove-vRNINorthSouthIP', 'Get-vRNISettingsVIDM',
94 | 'Set-vRNISettingsVIDM', 'Get-vRNISettingsUserGroup',
95 | 'Set-vRNISettingsUserGroup', 'Remove-vRNISettingsUserGroup',
96 | 'Get-vRNISettingsUser', 'Set-vRNISettingsUser',
97 | 'Remove-vRNISettingsUser', 'Get-vRNIAuditLogs',
98 | 'Get-vRNIApplicationMemberVM', 'Set-vRNIUserPassword',
99 | 'Get-vRNIKubernetesServices', 'Update-vRNIDataSourceData',
100 | 'Update-vRNINSXvControllerClusterPassword', 'Get-vRNIEntityNames',
101 | 'Invoke-vRNISearch', 'Get-vRNILicensing', 'Test-vRNILicensing',
102 | 'Install-vRNILicensing', 'Remove-vRNILicensing', 'Get-vRNIBackup',
103 | 'Get-vRNIBackupStatus', 'Remove-vRNIBackup', 'Enable-vRNIBackup',
104 | 'Disable-vRNIBackup', 'Set-vRNIBackup', 'Get-vRNIDatabusSubscriber',
105 | 'New-vRNIDatabusSubscriber', 'Remove-vRNIDatabusSubscriber',
106 | 'Get-vRNISDDCGroup', 'Get-vRNIVMCDirectConnect',
107 | 'Get-vRNIVMCDirectConnectInterface', 'Get-vRNISwitchPort',
108 | 'Get-vRNILogicalRouter', 'Get-vRNIVMwareTransitGateway',
109 | 'Get-vRNINSXTIPsecVPNSessions', 'Get-vRNISettingsLoginBanner',
110 | 'Set-vRNISettingsLoginBanner', 'Remove-vRNISettingsLoginBanner'
111 |
112 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
113 | CmdletsToExport = '*'
114 |
115 | # Variables to export from this module
116 | VariablesToExport = '*'
117 |
118 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
119 | AliasesToExport = '*'
120 |
121 | # DSC resources to export from this module
122 | # DscResourcesToExport = @()
123 |
124 | # List of all modules packaged with this module
125 | # ModuleList = @()
126 |
127 | # List of all files packaged with this module
128 | # FileList = @()
129 |
130 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
131 | PrivateData = @{
132 |
133 | PSData = @{
134 |
135 | # Tags applied to this module. These help with module discovery in online galleries.
136 | # Tags = @()
137 |
138 | # A URL to the license for this module.
139 | LicenseUri = 'https://github.com/PowervRNI/powervrni/blob/master/LICENSE.md'
140 |
141 | # A URL to the main website for this project.
142 | ProjectUri = 'https://github.com/PowervRNI/powervrni'
143 |
144 | # A URL to an icon representing this module.
145 | # IconUri = ''
146 |
147 | # ReleaseNotes of this module
148 | ReleaseNotes = '### v6.5.1 - 2022-03-07
149 | - \[fixed] Change the application page size to 100 to fix seeing an error about a hard limit in vRNI 6.5.1'
150 |
151 | # Prerelease string of this module
152 | # Prerelease = ''
153 |
154 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save
155 | # RequireLicenseAcceptance = $false
156 |
157 | # External dependent modules of this module
158 | # ExternalModuleDependencies = @()
159 |
160 | } # End of PSData hashtable
161 |
162 | } # End of PrivateData hashtable
163 |
164 | # HelpInfo URI of this module
165 | # HelpInfoURI = ''
166 |
167 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
168 | # DefaultCommandPrefix = ''
169 |
170 | }
171 |
172 |
--------------------------------------------------------------------------------
/publish/psgallery/PowervRNI/PowervRNI.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'PowervRNI'
3 | #
4 | # Generated by: Martijn Smit
5 | #
6 | # Generated on: 3/7/2022
7 | #
8 |
9 | @{
10 |
11 | # Script module or binary module file associated with this manifest.
12 | RootModule = 'PowervRNI.psm1'
13 |
14 | # Version number of this module.
15 | ModuleVersion = '6.51.185'
16 |
17 | # Supported PSEditions
18 | # CompatiblePSEditions = @()
19 |
20 | # ID used to uniquely identify this module
21 | GUID = 'a34be6be-3dc1-457a-aea3-d4263481ed79'
22 |
23 | # Author of this module
24 | Author = 'Martijn Smit'
25 |
26 | # Company or vendor of this module
27 | CompanyName = 'VMware'
28 |
29 | # Copyright statement for this module
30 | Copyright = 'Copyright 2022 VMware. All rights reserved.'
31 |
32 | # Description of the functionality provided by this module
33 | Description = 'A PowerShell module to talk to the vRealize Network Insight API'
34 |
35 | # Minimum version of the PowerShell engine required by this module
36 | PowerShellVersion = '6.0'
37 |
38 | # Name of the PowerShell host required by this module
39 | # PowerShellHostName = ''
40 |
41 | # Minimum version of the PowerShell host required by this module
42 | # PowerShellHostVersion = ''
43 |
44 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
45 | DotNetFrameworkVersion = '4.0'
46 |
47 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
48 | # ClrVersion = ''
49 |
50 | # Processor architecture (None, X86, Amd64) required by this module
51 | # ProcessorArchitecture = ''
52 |
53 | # Modules that must be imported into the global environment prior to importing this module
54 | # RequiredModules = @()
55 |
56 | # Assemblies that must be loaded prior to importing this module
57 | # RequiredAssemblies = @()
58 |
59 | # Script files (.ps1) that are run in the caller's environment prior to importing this module.
60 | # ScriptsToProcess = @()
61 |
62 | # Type files (.ps1xml) to be loaded when importing this module
63 | # TypesToProcess = @()
64 |
65 | # Format files (.ps1xml) to be loaded when importing this module
66 | # FormatsToProcess = @()
67 |
68 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
69 | # NestedModules = @()
70 |
71 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
72 | FunctionsToExport = 'Connect-vRNIServer', 'Connect-NIServer', 'Disable-vRNIDataSource',
73 | 'Disconnect-vRNIServer', 'Enable-vRNIDataSource',
74 | 'Get-vRNIAPIVersion', 'Get-vRNIApplication',
75 | 'Get-vRNIApplicationTier', 'Get-vRNIDataSource', 'Get-vRNIDatastore',
76 | 'Get-vRNIDistributedSwitch', 'Get-vRNIDistributedSwitchPortGroup',
77 | 'Get-vRNIEntity', 'Get-vRNIEntityName', 'Get-vRNIFirewallRule',
78 | 'Get-vRNIFlow', 'Get-vRNIHost', 'Get-vRNIHostVMKNic', 'Get-vRNIIPSet',
79 | 'Get-vRNIL2Network', 'Get-vRNINodes', 'Get-vRNINSXManager',
80 | 'Get-vRNIProblem', 'Get-vRNIRecommendedRules',
81 | 'Get-vRNIRecommendedRulesNsxBundle', 'Get-vRNISecurityGroup',
82 | 'Get-vRNISecurityTag', 'Get-vRNIService', 'Get-vRNIServiceGroup',
83 | 'Get-vRNIvCenter', 'Get-vRNIvCenterCluster',
84 | 'Get-vRNIvCenterDatacenter', 'Get-vRNIvCenterFolder', 'Get-vRNIVM',
85 | 'Get-vRNIVMvNIC', 'Get-vRNIDataSourceSNMPConfig', 'Get-vRNISDDC',
86 | 'Invoke-vRNIRestMethod', 'New-vRNIApplication',
87 | 'New-vRNIApplicationTier', 'New-vRNIDataSource',
88 | 'Remove-vRNIApplication', 'Remove-vRNIApplicationTier',
89 | 'Remove-vRNIDataSource', 'Set-vRNIDataSourceSNMPConfig',
90 | 'New-vRNISubnetMapping', 'Get-vRNISubnetMapping',
91 | 'Get-vRNIEastWestIP', 'Add-vRNIEastWestIP', 'Remove-vRNIEastWestIP',
92 | 'Get-vRNINorthSouthIP', 'Add-vRNINorthSouthIP',
93 | 'Remove-vRNINorthSouthIP', 'Get-vRNISettingsVIDM',
94 | 'Set-vRNISettingsVIDM', 'Get-vRNISettingsUserGroup',
95 | 'Set-vRNISettingsUserGroup', 'Remove-vRNISettingsUserGroup',
96 | 'Get-vRNISettingsUser', 'Set-vRNISettingsUser',
97 | 'Remove-vRNISettingsUser', 'Get-vRNIAuditLogs',
98 | 'Get-vRNIApplicationMemberVM', 'Set-vRNIUserPassword',
99 | 'Get-vRNIKubernetesServices', 'Update-vRNIDataSourceData',
100 | 'Update-vRNINSXvControllerClusterPassword', 'Get-vRNIEntityNames',
101 | 'Invoke-vRNISearch', 'Get-vRNILicensing', 'Test-vRNILicensing',
102 | 'Install-vRNILicensing', 'Remove-vRNILicensing', 'Get-vRNIBackup',
103 | 'Get-vRNIBackupStatus', 'Remove-vRNIBackup', 'Enable-vRNIBackup',
104 | 'Disable-vRNIBackup', 'Set-vRNIBackup', 'Get-vRNIDatabusSubscriber',
105 | 'New-vRNIDatabusSubscriber', 'Remove-vRNIDatabusSubscriber',
106 | 'Get-vRNISDDCGroup', 'Get-vRNIVMCDirectConnect',
107 | 'Get-vRNIVMCDirectConnectInterface', 'Get-vRNISwitchPort',
108 | 'Get-vRNILogicalRouter', 'Get-vRNIVMwareTransitGateway',
109 | 'Get-vRNINSXTIPsecVPNSessions', 'Get-vRNISettingsLoginBanner',
110 | 'Set-vRNISettingsLoginBanner', 'Remove-vRNISettingsLoginBanner'
111 |
112 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
113 | CmdletsToExport = '*'
114 |
115 | # Variables to export from this module
116 | VariablesToExport = '*'
117 |
118 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
119 | AliasesToExport = '*'
120 |
121 | # DSC resources to export from this module
122 | # DscResourcesToExport = @()
123 |
124 | # List of all modules packaged with this module
125 | # ModuleList = @()
126 |
127 | # List of all files packaged with this module
128 | # FileList = @()
129 |
130 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
131 | PrivateData = @{
132 |
133 | PSData = @{
134 |
135 | # Tags applied to this module. These help with module discovery in online galleries.
136 | # Tags = @()
137 |
138 | # A URL to the license for this module.
139 | LicenseUri = 'https://github.com/PowervRNI/powervrni/blob/master/LICENSE.md'
140 |
141 | # A URL to the main website for this project.
142 | ProjectUri = 'https://github.com/PowervRNI/powervrni'
143 |
144 | # A URL to an icon representing this module.
145 | # IconUri = ''
146 |
147 | # ReleaseNotes of this module
148 | ReleaseNotes = '### v6.5.1 - 2022-03-07
149 | - \[fixed] Change the application page size to 100 to fix seeing an error about a hard limit in vRNI 6.5.1'
150 |
151 | # Prerelease string of this module
152 | # Prerelease = ''
153 |
154 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save
155 | # RequireLicenseAcceptance = $false
156 |
157 | # External dependent modules of this module
158 | # ExternalModuleDependencies = @()
159 |
160 | } # End of PSData hashtable
161 |
162 | } # End of PrivateData hashtable
163 |
164 | # HelpInfo URI of this module
165 | # HelpInfoURI = ''
166 |
167 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
168 | # DefaultCommandPrefix = ''
169 |
170 | }
171 |
172 |
--------------------------------------------------------------------------------
/examples/cmdb-import-from-servicenow.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Examples
2 | #
3 | # Example: Import Applications from ServiceNow
4 | #
5 | # START Description
6 | # Retrieves applications from the CMDB ServiceNow, and imports them into vRNI.
7 | # Note: is now a native vRNI feature, the script is still here to serve as an example.
8 | # END Description
9 | #
10 | # More info: https://lostdomain.org/2018/11/19/integrating-servicenow-with-network-insight/
11 | #
12 | # Martijn Smit (@smitmartijn)
13 | # msmit@vmware.com
14 | # Version 1.0
15 |
16 |
17 | ## Start editing here ##
18 |
19 | # ServiceNow configuration; login credentials & URL
20 | $CONFIG_SNOW_USER = "admin"
21 | $CONFIG_SNOW_PASS = "VMware!"
22 | $CONFIG_SNOW_URL = "https://myinstance.service-now.com"
23 |
24 | # vRealize Network Insight config; login credentials & URL
25 | $CONFIG_vRNI_SERVER = "platform.networkinsight.lab.local"
26 | $CONFIG_vRNI_USER = "admin@local"
27 | $CONFIG_vRNI_PASS = "VMware1!"
28 |
29 | # We're using a filter to find only applications in ServiceNow with this in its name
30 | $APP_FILTER = "VMworld"
31 |
32 | ## Stop editing here ##
33 |
34 | # ServiceNow basic auth setup
35 | $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $CONFIG_SNOW_USER, $CONFIG_SNOW_PASS)))
36 |
37 | # Check if PowervRNI is installed. If not, throw an error, if yes, load it.
38 | if (!(Get-Module -ListAvailable -Name PowervRNI)) {
39 | throw "Please install PowervRNI (http://github.com/PowervRNI/powervrni) first by running: Install-Module PowervRNI"
40 | }
41 | Import-Module PowervRNI
42 |
43 | # This function is used to discover dependancies of configuration items (CIs) and loop through them to find any virtual machines
44 | # attached to the application. This function is called multiple times
45 | function get_children($outbound_relations, $depth) {
46 | # Outbound relations is an array of CI IDs that SNOW returns that have a relation with the current CI.
47 | foreach ($relation in $outbound_relations) {
48 | # The values are the actual CI IDs that we should use to request more information on the CI (and see if it's a VM)
49 | foreach ($val in $relation.target.value) {
50 | # Request details of CI ID
51 | $url = "$($CONFIG_SNOW_URL)/api/now/cmdb/instance/cmdb_ci/$($val)"
52 | $info = Invoke-RestMethod -Uri $url -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) } -UseBasicParsing
53 |
54 | # Is it a VM? If yes, then save the details
55 | if ($info.result.attributes.sys_class_name -eq "cmdb_ci_vmware_instance") {
56 | # I'm using the first bit of the VM name as the tier name. For instance: App-VM01 will be translated to tier: App
57 | $vm_name = $info.result.attributes.name
58 | # Split the VM name on "-" and grab the second to last element (App-VM01 = App) for the tier name
59 | $vm_name_pieces = $vm_name.Split("-")
60 | $tier_name = $vm_name_pieces[-2]
61 |
62 | # Initialise the tier array to save the VM names to
63 | if ($null -eq $Script:tier_list[$tier_name]) {
64 | $Script:tier_list[$tier_name] = @()
65 | $Script:number_of_tiers++
66 | }
67 |
68 | # If the tier does not already contain this VM (maybe from another CI relation), save it to memory
69 | if (!($Script:tier_list[$tier_name].Contains($vm_name))) {
70 | $Script:tier_list[$tier_name] += $vm_name
71 | $Script:number_of_vms++
72 |
73 | Write-Host -Foreground Yellow "VM '$($vm_name)' found for tier '$($tier_name)'"
74 | }
75 |
76 | # This is a special one; the correlation field on a CI is a text field that you can fill out in SNOW.
77 | # I'm using that field to couple a load balancing IP address to the VM. That means the VM is behind a load
78 | # balancer with that specific IP address. Save that IP address to also put in the vRNI Application, so connections
79 | # to the load balancer are also put into the vRNI Application context.
80 | # Note: you can also put any load balancer VM (i.e. NSX Edge) into the SNOW CI as a regular VM and this script will
81 | # also pick it up.
82 | if ($info.result.attributes.correlation_id -ne "") {
83 | $tier_name = "LB-$($tier_name)"
84 | if ($null -eq $Script:tier_list[$tier_name]) {
85 | $Script:tier_list[$tier_name] = @()
86 | $Script:number_of_tiers++
87 | }
88 |
89 | $vm_name = $info.result.attributes.correlation_id
90 | if (!($Script:tier_list[$tier_name].Contains($vm_name))) {
91 | $Script:tier_list[$tier_name] += $vm_name
92 | Write-Host -Foreground Yellow "IP Address '$($vm_name)' found for tier '$($tier_name)'"
93 | }
94 | }
95 | }
96 |
97 | # See if the CI has outbound relations to other CIs and if so, have get_children dive into those relations.
98 | if ($info.result.outbound_relations -ne "") {
99 | get_children($info.result.outbound_relations, ($depth + 1))
100 | }
101 | }
102 | }
103 | }
104 |
105 | # Connect PowervRNI
106 | Write-Host "Connecting PowervRNI to Network Insight.."
107 | $conn = Connect-vRNIServer -Server $CONFIG_vRNI_SERVER -User $CONFIG_vRNI_USER -Password ($CONFIG_VRNI_PASS | ConvertTo-SecureString -AsPlainText -Force)
108 | if (!$conn) {
109 | throw "Connection to Network Insight failed! Stopping."
110 | }
111 |
112 | # Execute a SNOW API call to get all defined application constructs
113 | Write-Host "Connecting to ServiceNow to retrieve CMDB application list.."
114 | $url = "$($CONFIG_SNOW_URL)/api/now/table/cmdb_ci_appl"
115 | $result = Invoke-RestMethod -Uri $url -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) } -UseBasicParsing
116 |
117 | # Go through all top-level applications that were returned
118 | foreach ($app in $result.result) {
119 | # We're limiting our import by using a name filter. If you want to import everything, comment this if statement out.
120 | if ($app.name.Contains($APP_FILTER)) {
121 | # Initialise a couple of variables to save the application info too
122 | $Script:tier_list = @{}
123 | $Script:number_of_tiers = 0
124 | $Script:number_of_vms = 0
125 |
126 | Write-Host -ForegroundColor green "Found an application with $($APP_FILTER) in it: $($app.name)"
127 |
128 | # Dig into the found application by retrieving the app details and then having get_children dive into the outbound relations
129 | $url = "$($CONFIG_SNOW_URL)/api/now/cmdb/instance/cmdb_ci/$($app.sys_id)"
130 | $result = Invoke-RestMethod -Uri $url -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) } -UseBasicParsing
131 | Write-Host "Looking for CIs inside '$($app.name)'.."
132 | get_children($result.result.outbound_relations, 1);
133 |
134 | # Considering get_children loops itself until it has discovered all VMs linked to an app, by now we have fully filled variables with the tiers and VMs
135 | Write-Host -ForegroundColor green "Found $($Script:number_of_vms) VMs in $($Script:number_of_tiers) tiers. Adding them to Network Insight via PowervRNI.."
136 |
137 | # Create Application container in vRNI
138 | $vrniApp = New-vRNIApplication -Name $app.name
139 | Write-Host -ForegroundColor Magenta "New-vRNIApplication -Name '$($app.name)'"
140 |
141 | # Now go through the discovered tiers and VMs
142 | foreach ($tier in $Script:tier_list.Keys) {
143 | # Get the list of VMs for this tier and go through them
144 | $vm_list = $($Script:tier_list.Item($tier))
145 | $vm_filter_list = ""
146 | $ip_filter_list = @()
147 | foreach ($vm in $vm_list) {
148 | # Test if the name is an IP address; if so, use an IP Filter instead of a VM Name filter
149 | if (($vm -As [IPAddress]) -As [Bool]) {
150 | $ip_filter_list += $vm
151 | }
152 | else {
153 | # This is a VM Name filter, add it to the VM Name filter string (and add an 'or' if this is not the first VM)
154 | if ($vm_filter_list -ne "") {
155 | $vm_filter_list += " or "
156 | }
157 | $vm_filter_list += "name = '$($vm)'"
158 | }
159 | }
160 |
161 | # If this is a VM Name filter, add that to vRNI using PowervRNI
162 | if ($vm_filter_list -ne "") {
163 | $new_tier = ($vrniApp | New-vRNIApplicationTier -Name $tier -VMFilters ("$($vm_filter_list)"))
164 | Write-Host -ForegroundColor Magenta "New-vRNIApplicationTier -Name $tier -VMFilters ("$($vm_filter_list)")"
165 | }
166 | else {
167 | # This is an IP filter, add that to vRNI
168 | $new_tier = ($vrniApp | New-vRNIApplicationTier -Name $tier -IPFilters $ip_filter_list)
169 | Write-Host -ForegroundColor Magenta "New-vRNIApplicationTier -Name $($tier) -IPFilters $($ip_filter_list)"
170 | }
171 | }
172 |
173 | Write-Host -ForegroundColor green "Application '$($app.name)' added to Network Insight!"
174 | Write-Host "----------------------"
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The GNU General Public License, Version 2, June 1991 (GPLv2)
2 | ============================================================
3 |
4 | > Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 | > 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
6 |
7 | Everyone is permitted to copy and distribute verbatim copies of this license
8 | document, but changing it is not allowed.
9 |
10 |
11 | Preamble
12 | --------
13 |
14 | The licenses for most software are designed to take away your freedom to share
15 | and change it. By contrast, the GNU General Public License is intended to
16 | guarantee your freedom to share and change free software--to make sure the
17 | software is free for all its users. This General Public License applies to most
18 | of the Free Software Foundation's software and to any other program whose
19 | authors commit to using it. (Some other Free Software Foundation software is
20 | covered by the GNU Lesser General Public License instead.) You can apply it to
21 | your programs, too.
22 |
23 | When we speak of free software, we are referring to freedom, not price. Our
24 | General Public Licenses are designed to make sure that you have the freedom to
25 | distribute copies of free software (and charge for this service if you wish),
26 | that you receive source code or can get it if you want it, that you can change
27 | the software or use pieces of it in new free programs; and that you know you can
28 | do these things.
29 |
30 | To protect your rights, we need to make restrictions that forbid anyone to deny
31 | you these rights or to ask you to surrender the rights. These restrictions
32 | translate to certain responsibilities for you if you distribute copies of the
33 | software, or if you modify it.
34 |
35 | For example, if you distribute copies of such a program, whether gratis or for a
36 | fee, you must give the recipients all the rights that you have. You must make
37 | sure that they, too, receive or can get the source code. And you must show them
38 | these terms so they know their rights.
39 |
40 | We protect your rights with two steps: (1) copyright the software, and (2) offer
41 | you this license which gives you legal permission to copy, distribute and/or
42 | modify the software.
43 |
44 | Also, for each author's protection and ours, we want to make certain that
45 | everyone understands that there is no warranty for this free software. If the
46 | software is modified by someone else and passed on, we want its recipients to
47 | know that what they have is not the original, so that any problems introduced by
48 | others will not reflect on the original authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software patents. We wish
51 | to avoid the danger that redistributors of a free program will individually
52 | obtain patent licenses, in effect making the program proprietary. To prevent
53 | this, we have made it clear that any patent must be licensed for everyone's free
54 | use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and modification
57 | follow.
58 |
59 |
60 | Terms And Conditions For Copying, Distribution And Modification
61 | ---------------------------------------------------------------
62 |
63 | **0.** This License applies to any program or other work which contains a notice
64 | placed by the copyright holder saying it may be distributed under the terms of
65 | this General Public License. The "Program", below, refers to any such program or
66 | work, and a "work based on the Program" means either the Program or any
67 | derivative work under copyright law: that is to say, a work containing the
68 | Program or a portion of it, either verbatim or with modifications and/or
69 | translated into another language. (Hereinafter, translation is included without
70 | limitation in the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not covered by
73 | this License; they are outside its scope. The act of running the Program is not
74 | restricted, and the output from the Program is covered only if its contents
75 | constitute a work based on the Program (independent of having been made by
76 | running the Program). Whether that is true depends on what the Program does.
77 |
78 | **1.** You may copy and distribute verbatim copies of the Program's source code
79 | as you receive it, in any medium, provided that you conspicuously and
80 | appropriately publish on each copy an appropriate copyright notice and
81 | disclaimer of warranty; keep intact all the notices that refer to this License
82 | and to the absence of any warranty; and give any other recipients of the Program
83 | a copy of this License along with the Program.
84 |
85 | You may charge a fee for the physical act of transferring a copy, and you may at
86 | your option offer warranty protection in exchange for a fee.
87 |
88 | **2.** You may modify your copy or copies of the Program or any portion of it,
89 | thus forming a work based on the Program, and copy and distribute such
90 | modifications or work under the terms of Section 1 above, provided that you also
91 | meet all of these conditions:
92 |
93 | * **a)** You must cause the modified files to carry prominent notices stating
94 | that you changed the files and the date of any change.
95 |
96 | * **b)** You must cause any work that you distribute or publish, that in whole
97 | or in part contains or is derived from the Program or any part thereof, to
98 | be licensed as a whole at no charge to all third parties under the terms of
99 | this License.
100 |
101 | * **c)** If the modified program normally reads commands interactively when
102 | run, you must cause it, when started running for such interactive use in the
103 | most ordinary way, to print or display an announcement including an
104 | appropriate copyright notice and a notice that there is no warranty (or
105 | else, saying that you provide a warranty) and that users may redistribute
106 | the program under these conditions, and telling the user how to view a copy
107 | of this License. (Exception: if the Program itself is interactive but does
108 | not normally print such an announcement, your work based on the Program is
109 | not required to print an announcement.)
110 |
111 | These requirements apply to the modified work as a whole. If identifiable
112 | sections of that work are not derived from the Program, and can be reasonably
113 | considered independent and separate works in themselves, then this License, and
114 | its terms, do not apply to those sections when you distribute them as separate
115 | works. But when you distribute the same sections as part of a whole which is a
116 | work based on the Program, the distribution of the whole must be on the terms of
117 | this License, whose permissions for other licensees extend to the entire whole,
118 | and thus to each and every part regardless of who wrote it.
119 |
120 | Thus, it is not the intent of this section to claim rights or contest your
121 | rights to work written entirely by you; rather, the intent is to exercise the
122 | right to control the distribution of derivative or collective works based on the
123 | Program.
124 |
125 | In addition, mere aggregation of another work not based on the Program with the
126 | Program (or with a work based on the Program) on a volume of a storage or
127 | distribution medium does not bring the other work under the scope of this
128 | License.
129 |
130 | **3.** You may copy and distribute the Program (or a work based on it, under
131 | Section 2) in object code or executable form under the terms of Sections 1 and 2
132 | above provided that you also do one of the following:
133 |
134 | * **a)** Accompany it with the complete corresponding machine-readable source
135 | code, which must be distributed under the terms of Sections 1 and 2 above on
136 | a medium customarily used for software interchange; or,
137 |
138 | * **b)** Accompany it with a written offer, valid for at least three years, to
139 | give any third party, for a charge no more than your cost of physically
140 | performing source distribution, a complete machine-readable copy of the
141 | corresponding source code, to be distributed under the terms of Sections 1
142 | and 2 above on a medium customarily used for software interchange; or,
143 |
144 | * **c)** Accompany it with the information you received as to the offer to
145 | distribute corresponding source code. (This alternative is allowed only for
146 | noncommercial distribution and only if you received the program in object
147 | code or executable form with such an offer, in accord with Subsection b
148 | above.)
149 |
150 | The source code for a work means the preferred form of the work for making
151 | modifications to it. For an executable work, complete source code means all the
152 | source code for all modules it contains, plus any associated interface
153 | definition files, plus the scripts used to control compilation and installation
154 | of the executable. However, as a special exception, the source code distributed
155 | need not include anything that is normally distributed (in either source or
156 | binary form) with the major components (compiler, kernel, and so on) of the
157 | operating system on which the executable runs, unless that component itself
158 | accompanies the executable.
159 |
160 | If distribution of executable or object code is made by offering access to copy
161 | from a designated place, then offering equivalent access to copy the source code
162 | from the same place counts as distribution of the source code, even though third
163 | parties are not compelled to copy the source along with the object code.
164 |
165 | **4.** You may not copy, modify, sublicense, or distribute the Program except as
166 | expressly provided under this License. Any attempt otherwise to copy, modify,
167 | sublicense or distribute the Program is void, and will automatically terminate
168 | your rights under this License. However, parties who have received copies, or
169 | rights, from you under this License will not have their licenses terminated so
170 | long as such parties remain in full compliance.
171 |
172 | **5.** You are not required to accept this License, since you have not signed
173 | it. However, nothing else grants you permission to modify or distribute the
174 | Program or its derivative works. These actions are prohibited by law if you do
175 | not accept this License. Therefore, by modifying or distributing the Program (or
176 | any work based on the Program), you indicate your acceptance of this License to
177 | do so, and all its terms and conditions for copying, distributing or modifying
178 | the Program or works based on it.
179 |
180 | **6.** Each time you redistribute the Program (or any work based on the
181 | Program), the recipient automatically receives a license from the original
182 | licensor to copy, distribute or modify the Program subject to these terms and
183 | conditions. You may not impose any further restrictions on the recipients'
184 | exercise of the rights granted herein. You are not responsible for enforcing
185 | compliance by third parties to this License.
186 |
187 | **7.** If, as a consequence of a court judgment or allegation of patent
188 | infringement or for any other reason (not limited to patent issues), conditions
189 | are imposed on you (whether by court order, agreement or otherwise) that
190 | contradict the conditions of this License, they do not excuse you from the
191 | conditions of this License. If you cannot distribute so as to satisfy
192 | simultaneously your obligations under this License and any other pertinent
193 | obligations, then as a consequence you may not distribute the Program at all.
194 | For example, if a patent license would not permit royalty-free redistribution of
195 | the Program by all those who receive copies directly or indirectly through you,
196 | then the only way you could satisfy both it and this License would be to refrain
197 | entirely from distribution of the Program.
198 |
199 | If any portion of this section is held invalid or unenforceable under any
200 | particular circumstance, the balance of the section is intended to apply and the
201 | section as a whole is intended to apply in other circumstances.
202 |
203 | It is not the purpose of this section to induce you to infringe any patents or
204 | other property right claims or to contest validity of any such claims; this
205 | section has the sole purpose of protecting the integrity of the free software
206 | distribution system, which is implemented by public license practices. Many
207 | people have made generous contributions to the wide range of software
208 | distributed through that system in reliance on consistent application of that
209 | system; it is up to the author/donor to decide if he or she is willing to
210 | distribute software through any other system and a licensee cannot impose that
211 | choice.
212 |
213 | This section is intended to make thoroughly clear what is believed to be a
214 | consequence of the rest of this License.
215 |
216 | **8.** If the distribution and/or use of the Program is restricted in certain
217 | countries either by patents or by copyrighted interfaces, the original copyright
218 | holder who places the Program under this License may add an explicit
219 | geographical distribution limitation excluding those countries, so that
220 | distribution is permitted only in or among countries not thus excluded. In such
221 | case, this License incorporates the limitation as if written in the body of this
222 | License.
223 |
224 | **9.** The Free Software Foundation may publish revised and/or new versions of
225 | the General Public License from time to time. Such new versions will be similar
226 | in spirit to the present version, but may differ in detail to address new
227 | problems or concerns.
228 |
229 | Each version is given a distinguishing version number. If the Program specifies
230 | a version number of this License which applies to it and "any later version",
231 | you have the option of following the terms and conditions either of that version
232 | or of any later version published by the Free Software Foundation. If the
233 | Program does not specify a version number of this License, you may choose any
234 | version ever published by the Free Software Foundation.
235 |
236 | **10.** If you wish to incorporate parts of the Program into other free programs
237 | whose distribution conditions are different, write to the author to ask for
238 | permission. For software which is copyrighted by the Free Software Foundation,
239 | write to the Free Software Foundation; we sometimes make exceptions for this.
240 | Our decision will be guided by the two goals of preserving the free status of
241 | all derivatives of our free software and of promoting the sharing and reuse of
242 | software generally.
243 |
244 |
245 | No Warranty
246 | -----------
247 |
248 | **11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
249 | THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
250 | STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
251 | "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
252 | BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
253 | PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
254 | PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
255 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
256 |
257 | **12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
258 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
259 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
260 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
261 | INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
262 | BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
263 | FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
264 | OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
265 |
--------------------------------------------------------------------------------
/examples/archive-flows-to-vrli/vrni-archive-flows-to-vrli.ps1:
--------------------------------------------------------------------------------
1 | # PowervRNI Examples
2 | #
3 | # Example: Archiving vRealize Network Insight flows to vRealize Log Insight
4 | #
5 | # START Description
6 | # This script connects to vRNI, retrieves the flows within a time window (the last time this script was run and now),
7 | # then checks whether the flow is located in the cache (more info in comments of cache code), and if not,
8 | # gathers metadata (VM & L2 network name), and finally sends the flow to vRLI using Send-vRLIMessage from vrealize-log-insight.ps1
9 | # END Description
10 | #
11 | # Start by filling out config.json with these values:
12 | #
13 | # "vrni_server": "your vRNI platform IP or hostname",
14 | # "vrni_credentials_file": "credentials.xml", <-- See below
15 | # "vrni_domain": "local", <-- Only change this if the vRNI user is using LDAP
16 | # "vrli_server": "your vRLI IP or hostname",
17 | # "cache_file": "flow-cache.json", <-- Leave this
18 | # "last_flows_ts": 1579273407 <-- leave this
19 | #
20 | # # credentials.xml
21 | # In order to login to vRNI, this script needs credentials. And let's not store these in plain text, so credentials.xml is a file with
22 | # masked credentials. Here's how to generate it:
23 | #
24 | # Open a PowerShell window and do this:
25 | #
26 | # PS > $credential = Get-Credential -Title "vRealize Network Insight Login"
27 | # PS > $credential | Export-CliXml -Path credentials.xml
28 | #
29 | # After generating the credentials.xml and configuring config.json, you can run this script by running:
30 | #
31 | # PS > ./vrni-archive-flows-to-vrli.ps1 -Config_JSON config.json
32 | #
33 | # Martijn Smit (@smitmartijn)
34 | # msmit@vmware.com
35 | # Version 1.0
36 |
37 | param (
38 | [parameter(Mandatory = $true, ValueFromPipeLine = $true, ValueFromPipeLineByPropertyName = $true)]
39 | [ValidateNotNullOrEmpty()]
40 | [string]$Config_JSON
41 | )
42 |
43 | # Test config existance
44 | if (!(Test-Path $Config_JSON)) {
45 | Throw "[$(Get-Date)] Configuration file not found! ($Config_JSON)"
46 | }
47 |
48 | # Include for Send-vRLIMessage function
49 | . "$PSScriptRoot\vrealize-log-insight.ps1"
50 |
51 | # Retrieve config and convert to object
52 | $Config = Get-Content -Path $Config_JSON | ConvertFrom-Json
53 |
54 |
55 | # Test for required params
56 | if (([bool]$Config.vrni_server -eq $False) -Or ([bool]$Config.vrni_credentials_file -eq $False) -Or ([bool]$Config.vrli_server -eq $False) -Or ([bool]$Config.cache_file -eq $False)) {
57 | Throw "[$(Get-Date)] Configuration file ($Config_JSON) needs to contain keys cache_file, vrli_server, vrni_server, and vrni_credentials_file!"
58 | }
59 |
60 | # Figure out the last_flow_ts variable; now-1hour when the ts is 0, use the timestamp otherwise
61 | $last_flow_ts = ([DateTimeOffset]::Now.ToUnixTimeSeconds() - 3600)
62 | if ($Config.last_flows_ts -ne 0) {
63 | $last_flow_ts = $Config.last_flows_ts
64 | }
65 | $new_flow_ts = ([DateTimeOffset]::Now.ToUnixTimeSeconds())
66 |
67 | # Connect to vRNI using the credentials file
68 | $creds = Import-CliXml -Path $Config.vrni_credentials_file
69 | Connect-vRNIServer -Server $Config.vrni_server -Credential $creds -Domain $Config.vrni_domain
70 |
71 | # Retrieve flows for the time window we need
72 | $max_flow_count = 250000
73 | Write-Host "[$(Get-Date)] Gettings flows from vRNI (this could take a while)"
74 | $raw_flows = Get-vRNIFlow -StartTime $last_flow_ts -EndTime $new_flow_ts -Limit $max_flow_count
75 | Write-Host "[$(Get-Date)] Found $($raw_flows.count) flows"
76 |
77 | if ($max_flow_count -eq $raw_flows.count) {
78 | Write-Host -ForegroundColor "yellow" "[$(Get-Date)] Warning: the number of flows returned is equal to max_flow_count $($max_flow_count). Please up the limit."
79 | }
80 |
81 | # Flows can exist for a long time; as long as the connection isn't shut down, or re-used, the flow record inside vRNI will stick around.
82 | # To prevent logging the same flow over and over again, we keep a local cache file and make sure to remove any flows here that are in that
83 | # cache file.
84 |
85 | # See if cache file exists, otherwise we'll start with an empty cache
86 | $flow_cache = @{}
87 | if (Test-Path $Config.cache_file) {
88 | $flow_cache = Get-Content -Path $Config.cache_file | ConvertFrom-Json -AsHashtable
89 | }
90 |
91 | # Home of the new cache
92 | $new_flow_cache = @{}
93 |
94 | # This will store the flows we'll submit to vRLI
95 | $flows = @()
96 |
97 | # Deduplicate flows with cache in mind
98 | foreach ($flow in $raw_flows) {
99 | # unique key is: src ip - dst ip - port - protocol
100 | # value will be the timestamp it's last seen, to be able to compare the time
101 | $key_name = ("{0}-{1}-{2}-{3}" -f $flow.source_ip.ip_address, $flow.destination_ip.ip_address, $flow.port.display, $flow.protocol)
102 |
103 | # if the flow is in the cache, check if it's older than 1 week.
104 | if ($flow_cache.ContainsKey($key_name)) {
105 | Write-Debug "Found flow in cache: $($key_name)"
106 | # If it is older than 1 week; don't remove it and repeat it to vRLI (safeguard)
107 | if (($new_flow_ts - $flow_cache[$key_name]) -gt (60 * 60 * 24 * 7)) {
108 | $flows += $flow
109 | Write-Debug " - Adding flow to queue because it's older than 1 week: $($key_name)"
110 | }
111 | }
112 | else {
113 | Write-Debug "Flow not found in cache: $($key_name)"
114 | # if the flow is not in the cache, it's a new one; add it!
115 | $flows += $flow
116 | }
117 |
118 | # update new cache
119 | if ($new_flow_cache.ContainsKey($key_name)) {
120 | $flow_cache[$key_name] = $new_flow_ts
121 | }
122 | else {
123 | $new_flow_cache.Add($key_name, $new_flow_ts)
124 | }
125 | }
126 |
127 | # Write new cache file
128 | Write-Debug "Saving new cache file"
129 | ($new_flow_cache | ConvertTo-Json | Out-File $Config.cache_file)
130 |
131 | # Go through the entity IDs related to the flows and get names for them
132 |
133 | # Start with VMs
134 | Write-Debug "Looking up VMs names"
135 | $vm_names = @{}
136 | $tmp_entity_lookup = @{}
137 | $tmp_entity_lookup.Add("entity_ids", @())
138 | $tmp_entity_count = 0
139 | foreach ($flow in $flows) {
140 | if ([bool]$flow.source_vm -ne $False) {
141 | # Only add it when the VM has not been discovered before
142 | if (!($vm_names.ContainsKey($flow.source_vm.entity_id))) {
143 | # Store entity id in tmp buffer, to be looked up at 100 entities, or in the last flow
144 | $tmp_entity_lookup.entity_ids += $flow.source_vm
145 | $tmp_entity_count++
146 | }
147 | }
148 | if ([bool]$flow.destination_vm -ne $False) {
149 | # Only add it when the VM has not been discovered before
150 | if (!($vm_names.ContainsKey($flow.destination_vm.entity_id))) {
151 | # Store entity id in tmp buffer, to be looked up at 100 entities, or in the last flow
152 | $tmp_entity_lookup.entity_ids += $flow.destination_vm
153 | $tmp_entity_count++
154 | }
155 | }
156 |
157 | # Do entity lookup with a 100 entities, or when it's the last flow
158 | if ($tmp_entity_count -eq 100 -Or $flow -eq $flows[-1]) {
159 | # Send a request to entities/fetch in order to bulk fetch the names of the VMs
160 | $requestBody = ConvertTo-Json $tmp_entity_lookup
161 | $entity_info = Invoke-vRNIRestMethod -Method POST -URI "/api/ni/entities/fetch" -Body $requestBody
162 | # Go through results and store the VM names
163 | foreach ($entity in $entity_info.results) {
164 | if (!($vm_names.ContainsKey($entity.entity_id))) {
165 | $vm_names.Add($entity.entity_id, @{name = $entity.entity.name; vc_id = $entity.entity.vendor_id; region = $entity.entity.region; type = $entity.entity_type })
166 | }
167 | }
168 | # Reset the tmp buffers
169 | $tmp_entity_lookup = @{}
170 | $tmp_entity_lookup.Add("entity_ids", @())
171 | $tmp_entity_count = 0
172 | }
173 | }
174 |
175 | # Also resolve L2 network names
176 | Write-Debug "Looking up L2 network names"
177 | $l2_names = @{}
178 | $tmp_entity_lookup = @{}
179 | $tmp_entity_lookup.Add("entity_ids", @())
180 | $tmp_entity_count = 0
181 | foreach ($flow in $flows) {
182 |
183 | if ([bool]$flow.source_l2_network -ne $False) {
184 | # Only add it when the L2 network has not been discovered before
185 | if (!($l2_names.ContainsKey($flow.source_l2_network.entity_id))) {
186 | # Store entity id in tmp buffer, to be looked up at 100 entities, or in the last flow
187 | # Work around a bug in the vRNI API - not all L2 network types has its entity_type set (like Azure VNets)
188 | if ([bool]$flow.source_l2_network.entity_type -eq $True) {
189 | $tmp_entity_lookup.entity_ids += $flow.source_l2_network
190 | $tmp_entity_count++
191 | }
192 | }
193 | }
194 | if ([bool]$flow.destination_l2_network -ne $False) {
195 | # Only add it when the L2 network has not been discovered before
196 | if (!($l2_names.ContainsKey($flow.destination_l2_network.entity_id))) {
197 | # Store entity id in tmp buffer, to be looked up at 100 entities, or in the last flow
198 | # Work around a bug in the vRNI API - not all L2 network types has its entity_type set (like Azure VNets)
199 | if ([bool]$flow.destination_l2_network.entity_type -eq $True) {
200 | $tmp_entity_lookup.entity_ids += $flow.destination_l2_network
201 | $tmp_entity_count++
202 | }
203 | }
204 | }
205 |
206 | # Do entity lookup with a 100 entities, or when it's the last flow
207 | if (($tmp_entity_count -eq 100 -Or $flow -eq $flows[-1]) -And $tmp_entity_count -gt 0) {
208 | # Send a request to entities/fetch in order to bulk fetch the names of the VMs
209 | $requestBody = ConvertTo-Json $tmp_entity_lookup
210 | $entity_info = Invoke-vRNIRestMethod -Method POST -URI "/api/ni/entities/fetch" -Body $requestBody
211 | # Go through results and store the VM names
212 | foreach ($entity in $entity_info.results) {
213 | if (!($l2_names.ContainsKey($entity.entity_id))) {
214 | $l2_names.Add($entity.entity_id, @{name = $entity.entity.name; vlan_id = $entity.entity.vlan_id; type = $entity.entity_type })
215 | }
216 | }
217 | # Reset the tmp buffers
218 | $tmp_entity_lookup = @{}
219 | $tmp_entity_lookup.Add("entity_ids", @())
220 | $tmp_entity_count = 0
221 | }
222 | }
223 |
224 | Write-Host "[$(Get-Date)] Looping through results and sending to vRLI"
225 | $flows_sent = 0
226 | foreach ($flow in $flows) {
227 | $flowDate = (Get-Date 01.01.1970) + ([System.TimeSpan]::fromseconds($flow.time))
228 |
229 | $log_message = "vRNI-FLOW $($flowDate.ToString('r')) $(($flow.firewall_action).ToUpper()) $($flow.protocol) $($flow.name)"
230 | $log_fields = @{}
231 |
232 | $log_fields.Add("__vrni_flow_firewall_action", $flow.firewall_action)
233 | $log_fields.Add("__vrni_flow_traffic_type", $flow.traffic_type)
234 | $log_fields.Add("__vrni_flow_tag", $flow.flow_tag)
235 | $log_fields.Add("__vrni_flow_source_ip", $flow.source_ip.ip_address)
236 | $log_fields.Add("__vrni_flow_destination_ip", $flow.destination_ip.ip_address)
237 | $log_fields.Add("__vrni_flow_port", $flow.port.display)
238 | $log_fields.Add("__vrni_flow_port_name", $flow.port.iana_name)
239 | $log_fields.Add("__vrni_flow_protocol", $flow.protocol)
240 | $log_fields.Add("__vrni_flow_timestamp", $flowDate)
241 |
242 | Write-Debug "Flow.name: $($flow.name)"
243 | Write-Debug "Flow.date: $($flowDate)"
244 | Write-Debug "Flow.firewall_action: $($flow.firewall_action)"
245 | Write-Debug "Flow.traffic_type: $($flow.traffic_type)"
246 | Write-Debug "Flow.flow_tag: $($flow.flow_tag)"
247 | Write-Debug "Flow.source_ip: $($flow.source_ip.ip_address)"
248 | Write-Debug "Flow.destination_ip: $($flow.destination_ip.ip_address)"
249 | Write-Debug "Flow.port: $($flow.port.display)"
250 | Write-Debug "Flow.port.name: $($flow.port.iana_name)"
251 | Write-Debug "Flow.protocol: $($flow.protocol)"
252 |
253 | # There are conditional fields, like when the flow contains a source or destination VM, or L2 network.
254 | # Below is checks whether these fields are present and adds them to the vRLI payload, if so.
255 | if ([bool]$flow.source_vm -ne $False) {
256 | $entity_id = $flow.source_vm.entity_id
257 | if ([bool]$vm_names[$entity_id].name -ne $False) {
258 | Write-Debug "Flow.source_vm: $($vm_names[$entity_id].name)"
259 | $log_fields.Add("__vrni_flow_source_vm", $vm_names[$entity_id].name)
260 | }
261 | if ([bool]$vm_names[$entity_id].type -ne $False) {
262 | Write-Debug "Flow.source_vm.type: $($vm_names[$entity_id].type)"
263 | $log_fields.Add("__vrni_flow_source_vm_type", $vm_names[$entity_id].type)
264 | }
265 | if ([bool]$vm_names[$entity_id].vc_id -ne $False) {
266 | Write-Debug "Flow.source_vm.vc_id: $($vm_names[$entity_id].vc_id)"
267 | $log_fields.Add("__vrni_flow_source_vm_vc_id", $vm_names[$entity_id].vc_id)
268 | }
269 | if ([bool]$vm_names[$entity_id].region -ne $False) {
270 | Write-Debug "Flow.source_vm.region: $($vm_names[$entity_id].region)"
271 | $log_fields.Add("__vrni_flow_source_vm_region", $vm_names[$entity_id].region)
272 | }
273 | }
274 | if ([bool]$flow.destination_vm -ne $False) {
275 | $entity_id = $flow.destination_vm.entity_id
276 | if ([bool]$vm_names[$entity_id].name -ne $False) {
277 | Write-Debug "Flow.destination_vm: $($vm_names[$entity_id].name)"
278 | $log_fields.Add("__vrni_flow_destination_vm", $vm_names[$entity_id].name)
279 | }
280 | if ([bool]$vm_names[$entity_id].type -ne $False) {
281 | Write-Debug "Flow.destination_vm.type: $($vm_names[$entity_id].type)"
282 | $log_fields.Add("__vrni_flow_destination_vm_type", $vm_names[$entity_id].type)
283 | }
284 | if ([bool]$vm_names[$entity_id].vc_id -ne $False) {
285 | Write-Debug "Flow.destination_vm.vc_id: $($vm_names[$entity_id].vc_id)"
286 | $log_fields.Add("__vrni_flow_destination_vm_vc_id", $vm_names[$entity_id].vc_id)
287 | }
288 | if ([bool]$vm_names[$entity_id].region -ne $False) {
289 | Write-Debug "Flow.destination_vm.region: $($vm_names[$entity_id].region)"
290 | $log_fields.Add("__vrni_flow_destination_vm_region", $vm_names[$entity_id].region)
291 | }
292 | }
293 |
294 | if ([bool]$flow.source_l2_network -ne $False) {
295 | $entity_id = $flow.source_l2_network.entity_id
296 | if ($l2_names.ContainsKey($entity_id)) {
297 | if ([bool]$l2_names[$entity_id].name -ne $False) {
298 | Write-Debug "Flow.source_l2_network.name: $($l2_names[$entity_id].name)"
299 | $log_fields.Add("__vrni_flow_source_l2_network", $l2_names[$entity_id].name)
300 | }
301 | if ([bool]$l2_names[$entity_id].vlan_id -ne $False) {
302 | Write-Debug "Flow.source_l2_network.vlan_id: $($l2_names[$entity_id].vlan_id)"
303 | $log_fields.Add("__vrni_flow_source_l2_network_vlan_id", $l2_names[$entity_id].vlan_id)
304 | }
305 | }
306 | }
307 | if ([bool]$flow.destination_l2_network -ne $False) {
308 | $entity_id = $flow.destination_l2_network.entity_id
309 | if ($l2_names.ContainsKey($entity_id)) {
310 | if ([bool]$l2_names[$entity_id].name -ne $False) {
311 | Write-Debug "Flow.destination_l2_network.name: $($l2_names[$entity_id].name)"
312 | $log_fields.Add("__vrni_flow_destination_l2_network", $l2_names[$entity_id].name)
313 | }
314 | if ([bool]$l2_names[$entity_id].vlan_id -ne $False) {
315 | Write-Debug "Flow.destination_l2_network.vlan_id: $($l2_names[$entity_id].vlan_id)"
316 | $log_fields.Add("__vrni_flow_destination_l2_network_vlan_id", $l2_names[$entity_id].vlan_id)
317 | }
318 | }
319 | }
320 |
321 | Write-Debug "================="
322 |
323 | # Send log message to vRLI!
324 | $output = Send-vRLIMessage -Server $Config.vrli_server -Message $log_message -Fields $log_fields
325 | $output | Out-Null
326 | $flows_sent++
327 | }
328 |
329 | # Save new timestamp to the configuration file
330 | ($Config.PSObject.Properties.Remove('last_flows_ts') | Out-Null)
331 | ($Config | Add-Member 'last_flows_ts' $new_flow_ts | Out-Null)
332 | ($Config | ConvertTo-Json | Out-File $Config_JSON)
333 |
334 | # Disconnect from vRNI to release the auth token
335 | Disconnect-vRNIServer
336 |
337 | Write-Host "[$(Get-Date)] Archived $($flows_sent) flows to vRealize Log Insight"
--------------------------------------------------------------------------------