RPort Example Scripts

Follow

The following scripts have been developed by RealVNC for use with RPort and are provided for example purposes.

Please edit the scripts to your requirements.

Copy and paste these scripts into the RPort script editor, edit as required and save to the RPort script library.

NOTE: These scripts are not supported by RealVNC Limited.

Scripts for Linux clients

NOTE: These scripts are for Debian-based Linux distributions unless otherwise stated.

Install RealVNC Server, cloud join and configure VNC Server - Debian-based and RHEL-based Linux 

Please review the settings in bold to ensure they meet your requirements.

# Installs/updates VNC Server and either licenses it offline with license key
# or joins to the cloud with a cloud connectivity token
# LINUX CLIENTS ONLY
#
# THIS SCRIPT IS PROVIDED BY REALVNC LIMITED AS PART OF REALONE

# CONFIGURE PARAMETERS BELOW TO YOUR REQUIREMENTS

# Set version of VNC Server to install, e.g. 7.1.0
# Defaults to Latest
{{$Version := "Latest"}}

# Set if we're using cloud or offline
# Accepted values: offline, cloud
{{$CloudOrOffline := "cloud"}}

# Set offline license to apply
# Not required if joining to the cloud
{{$OfflineLicense := ""}}

# Set cloud connectivity token to join VNC Server to the cloud
# Not required if using direct connections only
{{$CloudToken := "REPLACE WITH YOUR CLOUD JOIN TOKEN"}} # EDIT AS REQUIRED

# Set group to join VNC Server to - group must exist in the VNC Connect portal
# Optional
{{$CloudGroup := ""}}

######################### DO NOT EDIT BELOW THIS LINE ################################
{{$LinuxScriptPath := "/tmp/vnc.sh"}}

template:
file.managed:
- name: {{ $LinuxScriptPath }}
- contents: |
#!/bin/sh

Version="{{ $Version }}"
CloudOrOffline="{{ $CloudOrOffline }}"
OfflineLicense="{{ $OfflineLicense }}"
CloudToken="{{ $CloudToken }}"
CloudGroup="{{ $CloudGroup }}"

# Use TEMP for downloaded files
TempPath="/var/tmp"

# Detect architecture
Architecture="x64"
DetectedArchitecture="$(lscpu | grep Architecture | awk '{print $2}')"
if [ "$DetectedArchitecture" = "i386" ] || [ "$DetectedArchitecture" = "i686" ]; then
Architecture="x86"
elif [ "$DetectedArchitecture" = "aarch64" ]; then
Architecture="ARM64"
elif echo "$DetectedArchitecture" | grep -q "arm"; then
Architecture="ARM"
fi

# Set file extension based on package manager
FileExt=""
if type dpkg  /dev/null 2&1; then
FileExt=".deb"
elif type rpm  /dev/null 2&1; then
FileExt=".rpm"
fi

# Download VNC Server package from RealVNC website
curl -fsL --retry 3 "https://downloads.realvnc.com/download/file/vnc.files/\
VNC-Server-${Version}-Linux-${Architecture}${FileExt}" -o "${TempPath}/VNC${FileExt}"

# Install VNC Server package
if [ "$FileExt" = ".deb" ]; then
apt install -y "${TempPath}/VNC${FileExt}"
elif [ "$FileExt" = ".rpm" ]; then
yum install -y "${TempPath}/VNC${FileExt}"
fi

# Cleanup package
rm -f "${TempPath}/VNC${FileExt}"

# Determine if we are licensing by key or cloud joining
if [ "$CloudOrOffline" = "offline" ]; then
# Call vnclicense.exe to apply the key
/usr/bin/vnclicense -add "$OfflineLicense"
elif [ "$CloudOrOffline" = "cloud" ]; then
if [ "$(vncserver-x11 -service -cloudstatus | grep CloudJoined | cut -f2 -d':' | sed 's/,//')" = "false" ]; then
# If CloudGroup is set, use it to join VNC Server to that group - group must exist in the VNC Connect portal
if [ -n "$CloudGroup" ]; then
joinGroup="-joinGroup $CloudGroup"
# Call vncserver-x11 to do the cloud join
/usr/bin/vncserver-x11 -service -joinCloud "$CloudToken" "$joinGroup"
else
# Call vncserver.exe to do the cloud join
/usr/bin/vncserver-x11 -service -joinCloud "$CloudToken"
fi
fi
fi

# Add firewall rules if firewalld or ufw are detected
if type firewall-cmd  /dev/null 2&1; then
firewall-cmd --zone=public --permanent --add-service=vncserver-x11-serviced
firewall-cmd --reload
elif type ufw  /dev/null 2&1; then
ufw allow 5900
fi

# Disable Wayland is detected
gdmconf=""
if [ -f "/etc/gdm3/custom.conf" ]; then gdmconf="/etc/gdm3/custom.conf"; fi
if [ -f "/etc/gdm/custom.conf" ]; then gdmconf="/etc/gdm/custom.conf"; fi
if [ -n "$gdmconf" ]; then
if [ "$(grep -c "^#.*WaylandEnable=false" "$gdmconf")" -gt 0 ]; then
cp -a "$gdmconf" "$gdmconf.bak"
sed -i 's/^#.*WaylandEnable=.*/WaylandEnable=false/' "$gdmconf"
systemctl restart gdm*
fi
fi

systemctl enable vncserver-x11-serviced --now
systemctl restart vncserver-x11-serviced
- skip_verify: true
- mode: 0755
- encoding: UTF-8
cmd.run:
- names:
- sh -x {{ $LinuxScriptPath }}
- rm -f {{ $LinuxScriptPath }}
- shell: sh
# tacoscript to configure RealVNC Server
update-my-realvnc-server:
realvnc_server.config_update:
- encryption: PreferOn # EDIT AS REQUIRED
- server_mode: Service # EDIT AS REQUIRED
- query_connect: false # EDIT AS REQUIRED
- skip_reload: true # EDIT AS REQUIRED
- blank_screen: true # EDIT AS REQUIRED
- authentication: SystemAuth # EDIT AS REQUIRED
- permissions: %sudo:f # EDIT AS REQUIRED
- idle_timeout: '!UNSET!' # EDIT AS REQUIRED

Check RealVNC Server licensing

NOTE: RPort will display success (green status) for licensed VNC Servers and failure (red) where VNC Server is not installed and/or not licensed

#!/bin/bash

########################################################
# USE THIS SCRIPT TO CHECK REALVNC SERVER LICENSES ON #
# LINUX COMPUTERS. RUN THIS SCRIPT FROM RPORT #
#########################################################
# THIS SCRIPT IS PROVIDED BY REALVNC LIMITED AS PART OF REALONE

# LINUX CLIENTS ONLY
#
# THIS SCRIPT IS PROVIDED BY REALVNC LIMITED AS PART OF REALONE

if [ ! -x /usr/bin/vnclicense ];
then 
echo "RealVNC Server not installed";
exit 1;
fi

CLOUDSTATUS=`/usr/bin/vncserver-x11 -service -cloudstatus | grep 'CloudJoined' | awk -F ":|," '{print $2}'`

if [[ "$CLOUDSTATUS" == "false" ]];
then echo "Not cloud joined."; 
CLOUD=0; 
else CLOUD=1;
echo "This computer is joined to a RealVNC Connect cloud team"; 
#echo "Cloud details:"
#/usr/bin/vncserver-x11 -service -cloudstatus 2> /dev/null
fi

if [ $CLOUD -eq 0 ]; # if we aren't cloud joined, let's check for an offline license
then 
LICENSES=`/usr/bin/vnclicense -list`;
echo $LICENSES;
fi

if [[ "$LICENSES" == "No offline license found." ]];
then echo "No offline license found.";
exit 1;
else echo $LICS
fi

Unjoin RealVNC Server from Cloud and uninstall RealVNC Server

#!/bin/bash

# USE THIS SCRIPT TO *REMOVE* REALVNC SERVER FROM LINUX CLIENTS
#
# LINUX CLIENTS ONLY
#
# THIS SCRIPT IS PROVIDED BY REALVNC LIMITED AS PART OF REALONE

# stop the process
systemctl stop vncserver-x11-serviced
# unjoin vncserver from cloud then blat the install

# remove from cloud
echo "*** Performing cloud leave ***"
/usr/bin/vncserver-x11 -service -leavecloud > /dev/null 2>&1

echo "*** Removing Package ***";
apt purge -y realvnc-vnc-server;
echo "*** Removing RealVNC Server directories ***";
rm -rf /etc/vnc;
rm -rf /root/.vnc;
systemctl daemon-reload

Configure RealVNC Server parameters

Please review the settings in bold to ensure they meet your requirements.

# USE THIS SCRIPT TO CONFIGURE REALVNC SERVER FOR LINUX
# NOTE: EDIT THE SETTINGS AS REQUIRED TO MEET YOUR REQUIREMENTS
#
# For further information on RealVNC Server parameters, see:
# https://help.realvnc.com/hc/en-us/articles/360002251297-VNC-Server-Parameter-Reference-
#
# LINUX CLIENTS ONLY
#
# THIS SCRIPT IS PROVIDED BY REALVNC LIMITED AS PART OF REALONE

update-my-realvnc-server: 
realvnc_server.config_update:
- encryption: PreferOn # EDIT AS REQUIRED
- server_mode: Service # EDIT AS REQUIRED
- query_connect: false # EDIT AS REQUIRED
- blank_screen: true # EDIT AS REQUIRED
- authentication: SystemAuth # EDIT AS REQUIRED
- permissions: %sudo:f # EDIT AS REQUIRED
- idle_timeout: '!UNSET!' # EDIT AS REQUIRED

Enable ufw firewall and add a rule for SSH

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable

Windows scripts

Install RealVNC Server, cloud join and configure VNC Server

Please review the settings in bold to ensure they meet your requirements.

# Installs/updates VNC Server and either licenses it offline with license key 
# or joins to the cloud with a cloud connectivity token
# THIS SCRIPT IS PROVIDED BY REALVNC LIMITED AS PART OF REALONE

# CONFIGURE PARAMETERS BELOW TO YOUR REQUIREMENTS

# Set version of VNC Server to install, e.g. 7.1.0
# Defaults to Latest
{{$Version := "Latest"}}

# Set if we're using cloud or offline
# Accepted values: offline, cloud
{{$CloudOrOffline := "cloud"}}

# Set offline license to apply
# Not required if joining to the cloud
{{$OfflineLicense := ""}}

# Set cloud connectivity token to join VNC Server to the cloud
# Not required if using direct connections only
{{$CloudToken := "REPLACE WITH YOUR CLOUD JOIN TOKEN"}} # EDIT AS REQUIRED

# Set group to join VNC Server to - group must exist in the VNC Connect portal
# Optional
{{$CloudGroup := ""}}

# DO NOT EDIT BELOW THIS LINE
{{$WindowsScriptPath := "C:\\Windows\\Temp\\vnc.ps1"}}

template:
file.managed:
- name: {{ $WindowsScriptPath }}
- contents: |
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$Version = "{{ $Version }}"
$CloudOrOffline = "{{ $CloudOrOffline }}"
$OfflineLicense = "{{ $OfflineLicense }}"
$CloudToken = "{{ $CloudToken }}"
$CloudGroup = "{{ $CloudGroup }}"

# Use TEMP for downloaded files
$TempPath = $env:TEMP

# Detect architecture
$Architecture = "64bit"
if ((Get-WmiObject win32_operatingsystem | select osarchitecture).osarchitecture -ne "64-bit"){
$Architecture = "32bit"
}

# Download MSI archive from RealVNC website
Invoke-WebRequest -URI "https://downloads.realvnc.com/download/file/vnc.files/VNC-Server-$Version-Windows-msi.zip" -OutFile "$TempPath/VNC_MSIs.zip" 

# Unzip downloaded archive - this requires Powershell 5
Expand-Archive "$TempPath/VNC_MSIs.zip" -DestinationPath "$TempPath/VNC_MSIs" -Force

# Cleanup downloaded archive now that it's been extracted
Remove-Item -Path "$TempPath\VNC_MSIs.zip"

# Select MSI matching OS architecture
$MSIFilename = Get-ChildItem "$TempPath\VNC_MSIs\*$Architecture*.msi" | Select-Object -ExpandProperty Name

# Install VNC Server MSI silently
Start-Process msiexec.exe -Wait -ArgumentList "/I $TempPath\VNC_MSIs\$MSIFilename /qn"

# Cleanup MSIs
Remove-Item -Path "$TempPath\VNC_MSIs" -Recurse

# Determine if we are licensing by key or cloud joining
if ($CloudOrOffline -eq "offline"){
# Call vnclicense.exe to apply the key
Start-Process "C:\Program Files\RealVNC\VNC Server\vnclicense.exe" -Wait -ArgumentList "-add $OfflineLicense"
}
elseif ($CloudOrOffline -eq "cloud"){
if ((& 'C:\Program Files\RealVNC\VNC Server\vncserver.exe' -service -cloudstatus | ConvertFrom-JSON | Select-Object -ExpandProperty CloudJoined) -eq $false){
# If CloudGroup is set, use it to join VNC Server to that group - group must exist in the VNC Connect portal
if ($CloudGroup -ne ""){
$joinGroup = "-joinGroup $CloudGroup"
# Call vncserver.exe to do the cloud join
Start-Process "C:\Program Files\RealVNC\VNC Server\vncserver.exe" -Wait -ArgumentList "-service -joinCloud $CloudToken $joinGroup"
}
else{
Start-Process "C:\Program Files\RealVNC\VNC Server\vncserver.exe" -Wait -ArgumentList "-service -joinCloud $CloudToken"
}
}
}
- skip_verify: true
- mode: 0755
- encoding: UTF-8
cmd.run:
- names:
- PowerShell.exe -ExecutionPolicy Bypass -File {{ $WindowsScriptPath }}
- DEL {{ $WindowsScriptPath }}
- shell: cmd.exe
# tacoscript to configure RealVNC Server
update-my-realvnc-server: 
realvnc_server.config_update:
- encryption: PreferOn # EDIT AS REQUIRED
- server_mode: Service # EDIT AS REQUIRED
- query_connect: false # EDIT AS REQUIRED
- blank_screen: true # EDIT AS REQUIRED
- authentication: SystemAuth # EDIT AS REQUIRED
- permissions: %S-1-5-32-544:f # EDIT AS REQUIRED
- idle_timeout: '!UNSET!' # EDIT AS REQUIRED

Check RealVNC Server licensing

NOTE: RPort will display success (green status) for licensed VNC Servers and failure (red) where VNC Server is not installed and/or not licensed

# THIS SCRIPT IS PROVIDED BY REALVNC LIMITED AS PART OF REALONE

function Check-Cloud($command, $argument1, $argument2) {
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $command
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = $argument1,$argument2
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo

# Execute the command and store the output in a variable
try{
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
}
catch{
Write-Output "VNC Server not installed!"
exit 1
}

# Compare the output with the string No offline license found
if ($stdout.Contains("`"CloudJoined`":false")) {
# Throw an error with a custom message
Write-Output "Not cloud joined"
return
}
else {
# Return the output as normal
Write-Output "This computer is joined to a RealVNC Connect cloud team"
#Write-Output $stdout
$cloudjoined=$true
return 
}
}

function Check-Direct($command, $argument1) {
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $command
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = $argument1
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo

# Execute the command and store the output in a variable
try{
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
}
catch{
Write-Output "VNC Server not installed!"
exit 1
}

# Compare the output with the string No offline license found
if ($stdout.Trim() -eq "No offline license found.") {
# Throw an error with a custom message
Write-Output "No offline license found"
return
}
else {
# Return the output as normal
Write-Output $stdout
return 
}
}

Check-Cloud 'C:\Program Files\RealVNC\VNC Server\vncserver.exe' '-service' '-cloudstatus'

if ($cloudjoined -eq $false)
{ 
Check-Direct 'C:\Program Files\RealVNC\VNC Server\vnclicense.exe' '-list'
}
else { exit }

Unjoin RealVNC Server from Cloud and uninstall RealVNC Server

# THIS SCRIPT REMOVES REALVNC SERVER FROM WINDOWS CLIENTS
# WINDOWS CLIENTS ONLY
# THIS SCRIPT IS PROVIDED BY REALVNC LIMITED AS PART OF REALONE

write-host "Performing Leave Cloud and uninstalling RealVNC Server"

& "C:\Program Files\RealVNC\VNC Server\vncserver.exe" -service -leavecloud

$app = Get-WmiObject -Class Win32_Product | Where-Object { 
$_.Name -match "RealVNC Server" 
}
$app.Uninstall()

remove-item -path "HKLM:Software\RealVNC" -Recurse

Configure RealVNC Server parameters

Please review the settings in bold to ensure they meet your requirements. Note that %S-1-5-32-544 represents the Administrators group. 

Use the RealVNC permissions creator (download from https://www.realvnc.com/en/connect/download/vnc/) to build your permissions string as required.

# USE THIS SCRIPT TO CONFIGURE REALVNC SERVER FOR WINDOWS
# For further information on RealVNC Server parameters, see:
# https://help.realvnc.com/hc/en-us/articles/360002251297-VNC-Server-Parameter-Reference-

update-my-realvnc-server: 
realvnc_server.config_update:
- encryption: PreferOn
- server_mode: Service
- query_connect: false
- blank_screen: true
- authentication: SystemAuth
- permissions: %S-1-5-32-544:f
- idle_timeout: '!UNSET!'

Apply Windows updates

#TLS Setting
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

#Trust PowerShell Gallery - this will avoid you getting any prompts that it's untrusted
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted

#Install NuGet
Install-PackageProvider -name NuGet -Confirm:$false -Force

#Install Module
Install-Module PSWindowsUpdate

#Check what updates are required for this server
Get-WindowsUpdate

#Accept and install all the updates that it's found are required
Install-WindowsUpdate -AcceptAll -AutoReboot

$needReboot = (Get-WURebootStatus -Silent).RebootRequired

if ($needReboot)
{
Write-Host "Windows Update indicated that a reboot is needed."
}
else
{
Write-Host "Windows Update indicated that no reboot is required."
}

Enable Windows Firewall for all profiles (Domain, Public, Private)

Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
Write-Host "Windows Firewall Enabled for : Domain, Public, Private"

Check Windows Firewall is Enabled 

$FirewallStatus = 0
$SysFirewallReg1 = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\DomainProfile" -Name EnableFirewall | Select-Object -ExpandProperty EnableFirewall
If ($SysFirewallReg1 -eq 1) {
$FirewallStatus = 1
}

$SysFirewallReg2 = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\PublicProfile" -Name EnableFirewall | Select-Object -ExpandProperty EnableFirewall
If ($SysFirewallReg2 -eq 1) {
$FirewallStatus = ($FirewallStatus + 1)
}

$SysFirewallReg3 = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile" -Name EnableFirewall | Select-Object -ExpandProperty EnableFirewall
If ($SysFirewallReg3 -eq 1) {
$FirewallStatus = ($FirewallStatus + 1)
}

If ($FirewallStatus -eq 3) {Write-Host "Compliant"}
ELSE {Write-Host "Non-Compliant"}

Miscellaneous Scripts

Check RealVNC Server licensing (for Windows and Linux clients)

This is a bash script to collect RealVNC Server license details on Windows and Linux clients. The script can be run against RPort client groups, specific clients or clients with specific RPort tags. This script is not intended to be run via RPort's script execution mechanism.

The script produces an output similar to the below.

In this example, there are 2 computers without RealVNC server installed.

----- Results -----

Total no. RPort clients: 13
No. connected RPort clients: 13
No. disconnected RPort clients: 0

No. of clients targeted: 13
No. of Windows clients targeted: 4
No. of Linux clients targeted: 9

Clients with RealVNC Server: 11
Clients without RealVNC Server: 2
Licensed RealVNC Servers: 11
Unlicensed RealVNC Servers: 0
Online licensed RealVNC Servers: 11
Offline licensed RealVNC Servers: 0

Edit the script as necessary for your environment:

#!/bin/bash

RPORT_URL="https://rportserver.com" # EDIT AS APPROPRIATE
API_USERNAME="username" # EDIT AS APPROPRIATE
API_TOKEN=`cat /home/myrportapitoken` # EDIT AS APPROPRIATE

# ONLY USE ONE OF THE BELOW
GROUP_NAMES=("All_Windows_Computers" "All_Linux_Computers") # EDIT AS APPROPRIATE
#CLIENT_NAMES=("Computer1" "Computer2" "Computer3") # EDIT AS APPROPRIATE
#TAG_NAMES=("Tag1" "Tag2") # EDIT AS APPROPRIATE

##########################################################################
##########################################################################
######                                                              ######
######               DO NOT EDIT BELOW THIS SECTION                 ######
######                                                              ######
##########################################################################
##########################################################################

function curl_with_status_code {
    output_file="$1"
    target_url="$2"
    curl -sL -w "%{http_code}" -u "$AUTH_HEADER" -o "$output_file" --location -g "$target_url"
}

function join_by {
    local IFS="$1"
    shift
    echo "$*"
}

# $1 - message to print
# $2 - exit code
function exit_script {
    echo "$1"
    rm -rf "$WORK_DIR"
    exit "$2"
}

function execute_script {
    os_type="$1"
    shift
    script="$1"
    shift
    client_list=("$@")
    interpreter=""
    CLIENT_LIST_STRING=$(printf ',"%s"' "${client_list[@]}")
    TARGETS_STRING='"client_ids":['"${CLIENT_LIST_STRING:1}"'],'

    MAX_CLIENTS_SCRIPT="${#client_list[@]}"

    if [ "$os_type" = "Windows" ]; then
        interpreter="powershell"
    elif [ "$os_type" = "Linux" ]; then
        interpreter="/bin/bash"
    fi
    response=$(curl -sL -w "%{http_code}" --location "$RPORT_URL/api/v1/scripts" \
    --header 'Content-Type: application/json' \
    -u "$AUTH_HEADER" \
    --data "{$TARGETS_STRING"'
    "is_sudo":true,
    "interpreter":"'"$interpreter"'",
    "timeout_sec":60,
    "execute_concurrently":true,
    "script":"'"$script"'"
    }' -o "$WORK_DIR/scriptexecute.json")
    if [ "$response" -ne 200 ]; then
        echo "$response"
        exit_script "Something went wrong trying to execute the script!" 1
    fi
    JOB_ID=$(jq -r '.data.jid' "$WORK_DIR/scriptexecute.json")
    echo "Waiting 10 seconds to allow script execution to start on $MAX_CLIENTS_SCRIPT $os_type client(s)..."
    sleep 10
    echo "Querying RPort for script execution status for $MAX_CLIENTS_SCRIPT $os_type client(s)..."
    TARGET="$RPORT_URL/api/v1/auditlog?filter[affected_id]=$JOB_ID&filter[action]=execute.done&page[limit]=100"
    response=$(curl_with_status_code "$WORK_DIR/auditlog.json" "$TARGET")
    CLIENT_ENDED_TOTAL=$(jq -r '.meta.count' "$WORK_DIR/auditlog.json")
    echo "Script execution finished on $CLIENT_ENDED_TOTAL of $MAX_CLIENTS_SCRIPT $os_type client(s)..."
    while [ "$CLIENT_ENDED_TOTAL" -lt "$MAX_CLIENTS_SCRIPT" ]; do
        sleep 3
        response=$(curl_with_status_code "$WORK_DIR/auditlog.json" "$TARGET")
        CLIENT_ENDED_TOTAL=$(jq -r '.meta.count' "$WORK_DIR/auditlog.json")
        echo "Script execution finished on $CLIENT_ENDED_TOTAL of $MAX_CLIENTS_SCRIPT $os_type client(s)..."
    done
    echo "Processing results of script execution status for $os_type client(s)..."
    echo
    jq -r '.data[].response' "$WORK_DIR/auditlog.json" > "$WORK_DIR/responses.json"
    CLIENT_RESPONSES=$(wc -l < "$WORK_DIR/responses.json")
    while [ "$CLIENT_RESPONSES" -lt "$CLIENT_ENDED_TOTAL" ]; do
        response=$(curl_with_status_code "$WORK_DIR/auditlog.json" "$TARGET&page[offset]=$CLIENT_RESPONSES")
        jq -r '.data[].response' "$WORK_DIR/auditlog.json" >> "$WORK_DIR/responses.json"
        CLIENT_RESPONSES=$(wc -l < "$WORK_DIR/responses.json")
    done
    jq -rs '.[].result.stdout' "$WORK_DIR/responses.json" >> "$WORK_DIR/responses.txt"
}
WORK_DIR=/tmp/rport_vnc AUTH_HEADER="${API_USERNAME}:${API_TOKEN}" MAX_CLIENTS=0 TOTAL_CLIENTS=0 TOTAL_CLIENTS_CONNECTED=0 TOTAL_CLIENTS_DISCONNECTED=0 CLIENT_LIST=() CLIENT_LIST_WINDOWS=() CLIENT_LIST_LINUX=() mkdir -p "$WORK_DIR" response=$(curl_with_status_code "$WORK_DIR/clients.json" "$RPORT_URL/api/v1/clients") if [ "$response" -eq 200 ]; then   TOTAL_CLIENTS=$(jq -r '.meta.count' "$WORK_DIR/clients.json") else   exit_script "Error querying RPort for client list" 1 fi response=$(curl_with_status_code "$WORK_DIR/clients.json" "$RPORT_URL/api/v1/clients?filter[connection_state]=connected") if [ "$response" -eq 200 ]; then   TOTAL_CLIENTS_CONNECTED=$(jq -r '.meta.count' "$WORK_DIR/clients.json") else   exit_script "Error querying RPort for connected client list" 1 fi response=$(curl_with_status_code "$WORK_DIR/clients.json" "$RPORT_URL/api/v1/clients?filter[connection_state]=disconnected") if [ "$response" -eq 200 ]; then   TOTAL_CLIENTS_DISCONNECTED=$(jq -r '.meta.count' "$WORK_DIR/clients.json") else   exit_script "Error querying RPort for disconnected client list" 1 fi if [ "${#GROUP_NAMES[@]}" -gt 0 ]; then   for i in "${GROUP_NAMES[@]}"; do       response=$(curl_with_status_code "$WORK_DIR/group.json" "$RPORT_URL/api/v1/client-groups/$i" )       if [ "$response" -eq 404 ]; then           echo "Client group named $i not found, removing from list"           delete=("$i")           for target in "${delete[@]}"; do             for i2 in "${!GROUP_NAMES[@]}"; do               if [[ ${GROUP_NAMES[i2]} = "$target" ]]; then                 unset 'GROUP_NAMES[i2]'               fi             done           done       fi   done   TARGET="$RPORT_URL/api/v1/clients?filter[groups]="'or('"$(join_by "," "${GROUP_NAMES[@]}" | sed 's/ /%20/g')"')&filter[connection_state]=connected&fields[clients]=id,name,hostname,connection_state,os_kernel&page[limit]=500' elif [ "${#CLIENT_NAMES[@]}" -gt 0 ]; then   for i in "${CLIENT_NAMES[@]}"; do       response=$(curl_with_status_code "$WORK_DIR/clients.json" "$RPORT_URL/api/v1/clients?filter[connection_state]=connected&filter[name]=$i")       update=("$i")       for target in "${update[@]}"; do           for i2 in "${!CLIENT_NAMES[@]}"; do               if [[ ${CLIENT_NAMES[i2]} = "$target" ]]; then                   if [ "$(jq -r '.meta.count' "$WORK_DIR/clients.json")" -eq 0 ]; then                       echo "Connected client named $i not found, removing from list"                       unset 'CLIENT_NAMES[i2]'                   fi               fi           done       done   done   TARGET="$RPORT_URL/api/v1/clients?filter[name]="'or('"$(join_by "," "${CLIENT_NAMES[@]}" | sed 's/ /%20/g')"')&filter[connection_state]=connected&fields[clients]=id,name,hostname,connection_state,os_kernel&page[limit]=500'   #CLIENT_LIST=( "${CLIENT_NAMES[@]}" ) elif [ "${#TAG_NAMES[@]}" -gt 0 ]; then   TARGET="$RPORT_URL/api/v1/clients?filter[tags]="'or('"$(join_by "," "${TAG_NAMES[@]}" | sed 's/ /%20/g')"')&filter[connection_state]=connected&fields[clients]=id,name,hostname,connection_state,os_kernel&page[limit]=500' fi response=$(curl_with_status_code "$WORK_DIR/clients.json" "$TARGET") CLIENT_COUNT=0 if [ "$response" -eq 200 ]; then   CLIENT_COUNT=$(jq -r '.meta.count' "$WORK_DIR/clients.json")   jq -r '.data[]' "$WORK_DIR/clients.json" > "$WORK_DIR/client_list.json"   CLIENT_LIST_LENGTH=$(jq '.data | length' "$WORK_DIR/clients.json")   while [ "$CLIENT_LIST_LENGTH" -lt "$CLIENT_COUNT" ]; do       curl -fsL --location -g "$TARGET&page[offset]=$CLIENT_LIST_LENGTH" -u "$AUTH_HEADER" -o "$WORK_DIR/clients.json"       jq -r '.data[]' "$WORK_DIR/clients.json" >> "$WORK_DIR/client_list.json"       CLIENT_LIST_LENGTH=$(( CLIENT_LIST_LENGTH + $(jq '.data | length' "$WORK_DIR/clients.json") ))   done fi readarray -t CLIENT_LIST < <(jq -r '.id' "$WORK_DIR/client_list.json") readarray -t CLIENT_LIST_WINDOWS < <(jq -r 'select(.os_kernel=="windows") | .id' "$WORK_DIR/client_list.json") readarray -t CLIENT_LIST_LINUX < <(jq -r 'select(.os_kernel=="linux") | .id' "$WORK_DIR/client_list.json") MAX_CLIENTS="${#CLIENT_LIST[@]}" MAX_CLIENTS_WINDOWS="${#CLIENT_LIST_WINDOWS[@]}" MAX_CLIENTS_LINUX="${#CLIENT_LIST_LINUX[@]}" if [ "$MAX_CLIENTS" -eq 0 ]; then   exit_script "No eligible clients found!" 1 fi if [ "$MAX_CLIENTS_WINDOWS" -gt 0 ]; then   execute_script "Windows" "JGxpY2Vuc2VkID0gJGZhbHNlCiRsaWNlbnNldHlwZSA9ICIiCiRpbnN0YWxsZWQgPSAkdHJ1ZQoKIyBDcmVhdGUgb2JqZWN0cyBmb3IgUHJvY2VzcyBhbmQgUHJvY2Vzc1N0YXJ0SW5mbyB0aGF0IGNhbiBiZSByZS11c2VkCiRwID0gTmV3LU9iamVjdCBTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2VzcwokcGluZm8gPSBOZXctT2JqZWN0IFN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzU3RhcnRJbmZvCiRwaW5mby5SZWRpcmVjdFN0YW5kYXJkRXJyb3IgPSAkdHJ1ZQokcGluZm8uUmVkaXJlY3RTdGFuZGFyZE91dHB1dCA9ICR0cnVlCiRwaW5mby5Vc2VTaGVsbEV4ZWN1dGUgPSAkZmFsc2UKJHBpbmZvLkNyZWF0ZU5vV2luZG93ID0gJHRydWUKCiMgVGVzdCBmb3IgY2xvdWQgbGljZW5zZSBmaXJzdAokcGluZm8uRmlsZU5hbWUgPSAnQzpcUHJvZ3JhbSBGaWxlc1xSZWFsVk5DXFZOQyBTZXJ2ZXJcdm5jc2VydmVyLmV4ZScKJHBpbmZvLkFyZ3VtZW50cyA9ICctc2VydmljZScsJy1jbG91ZHN0YXR1cycKJHAuU3RhcnRJbmZvID0gJHBpbmZvCgojIEV4ZWN1dGUgdGhlIGNvbW1hbmQgYW5kIHN0b3JlIHRoZSBvdXRwdXQKdHJ5ewogICAgJHAuU3RhcnQoKSB8IE91dC1OdWxsCiAgICAkcC5XYWl0Rm9yRXhpdCgpCiAgICAkc3Rkb3V0ID0gJHAuU3RhbmRhcmRPdXRwdXQuUmVhZFRvRW5kKCkKICAgICRzdGRlcnIgPSAkcC5TdGFuZGFyZEVycm9yLlJlYWRUb0VuZCgpCn0KY2F0Y2h7CiAgICAjIFRoaXMgd2lsbCBlcnJvciBpZiB2bmNzZXJ2ZXIuZXhlIGlzbid0IGZvdW5kCiAgICAkaW5zdGFsbGVkID0gJGZhbHNlCn0KCmlmICgkaW5zdGFsbGVkIC1lcSAkZmFsc2UpewogICAgV3JpdGUtT3V0cHV0ICJSZWFsVk5DIFNlcnZlciBpcyBub3QgaW5zdGFsbGVkIgp9CmVsc2V7CiAgICAjIENoZWNrIG91dHB1dCB0byBkZXRlcm1pbmUgaWYgUmVhbFZOQyBTZXJ2ZXIgaXMgam9pbmVkIHRvIHRoZSBjbG91ZAogICAgaWYgKCEgJHN0ZG91dC5Db250YWlucygiYCJDbG91ZEpvaW5lZGAiOnRydWUiKSkgewogICAgICAgICMgUmVhbFZOQyBTZXJ2ZXIgaXNuJ3QgY2xvdWQgam9pbmVkLCBzbyBjaGVjayBmb3Igb2ZmbGluZSBsaWNlbnNlCiAgICAgICAgJHBpbmZvLkZpbGVOYW1lID0gJ0M6XFByb2dyYW0gRmlsZXNcUmVhbFZOQ1xWTkMgU2VydmVyXHZuY2xpY2Vuc2UuZXhlJwogICAgICAgICRwaW5mby5Bcmd1bWVudHMgPSAnLWxpc3QnCiAgICAgICAgJHAuU3RhcnRJbmZvID0gJHBpbmZvICAgIAogICAgICAgICRwLlN0YXJ0KCkgfCBPdXQtTnVsbAogICAgICAgICRwLldhaXRGb3JFeGl0KCkKICAgICAgICAkc3Rkb3V0ID0gJHAuU3RhbmRhcmRPdXRwdXQuUmVhZFRvRW5kKCkKICAgICAgICAkc3RkZXJyID0gJHAuU3RhbmRhcmRFcnJvci5SZWFkVG9FbmQoKQogICAgCiAgICAgICAgIyBDaGVjayBvdXRwdXQgdG8gZGV0ZXJtaW5lIGlmIFJlYWxWTkMgU2VydmVyIGhhcyBhbiBvZmZsaW5lIGxpY2Vuc2UKICAgICAgICBpZiAoJHN0ZG91dC5UcmltKCkgLWVxICJObyBvZmZsaW5lIGxpY2Vuc2UgZm91bmQuIikgewogICAgICAgICAgICAjIFJlYWxWTkMgU2VydmVyIGlzbid0IG9mZmxpbmUgbGljZW5zZWQsIGJ1dCBtYXkgYmUgYSBWNyBTZXJ2ZXIgd2l0aCBhIFY2IG9mZmxpbmUgbGljZW5zZSBzbyBjaGVjayBmb3IgdGhhdAogICAgICAgICAgICAkcGluZm8uRmlsZU5hbWUgPSAnQzpcUHJvZ3JhbSBGaWxlc1xSZWFsVk5DXFZOQyBTZXJ2ZXJcdm5jbGljZW5zZS5leGUnCiAgICAgICAgICAgICRwaW5mby5Bcmd1bWVudHMgPSAnLWxlZ2FjeWxpc3QnCiAgICAgICAgICAgICRwLlN0YXJ0SW5mbyA9ICRwaW5mbyAgICAKICAgICAgICAgICAgJHAuU3RhcnQoKSB8IE91dC1OdWxsCiAgICAgICAgICAgICRwLldhaXRGb3JFeGl0KCkKICAgICAgICAgICAgJHN0ZG91dCA9ICRwLlN0YW5kYXJkT3V0cHV0LlJlYWRUb0VuZCgpCiAgICAgICAgICAgICRzdGRlcnIgPSAkcC5TdGFuZGFyZEVycm9yLlJlYWRUb0VuZCgpCiAgICAgICAgICAgIAogICAgICAgICAgICAjIC1sZWdhY3lsaXN0IHdpbGwgZWl0aGVyIHJldHVybiBWNiBsaWNlbnNlIGRldGFpbHMsIG9yIHByaW50IG5vdGhpbmcgZWl0aGVyIGJlY2F1c2UgdGhlcmUgaXMgbm8gVjYgb2ZmbGluZSBsaWNlbnNlZC8tbGVnYWN5bGlzdGcgbm90IGJlaW5nIHJlY29nbmlzZWQgKFY2IFNlcnZlcikKICAgICAgICAgICAgaWYgKCRzdGRvdXQuTGVuZ3RoIC1ndCAwKXsKICAgICAgICAgICAgICAgICRsaWNlbnNlZCA9ICR0cnVlCiAgICAgICAgICAgICAgICAkbGljZW5zZXR5cGUgPSAib2ZmbGluZSIKICAgICAgICAgICAgfSAgICAgIAogICAgICAgIH0KICAgICAgICBlbHNlewogICAgICAgICAgICAkbGljZW5zZWQgPSAkdHJ1ZQogICAgICAgICAgICAkbGljZW5zZXR5cGUgPSAib2ZmbGluZSIKICAgICAgICB9CiAgICB9CiAgICBlbHNlIHsKICAgICAgICAkbGljZW5zZWQgPSAkdHJ1ZQogICAgICAgICRsaWNlbnNldHlwZSA9ICJvbmxpbmUiCiAgICB9CgogICAgaWYgKCRsaWNlbnNlZCl7CiAgICAgICAgaWYoJGxpY2Vuc2V0eXBlIC1lcSAib25saW5lIil7CiAgICAgICAgICAgICRyZXN1bHQgPSAiUmVhbFZOQyBTZXJ2ZXIgaXMgbGljZW5zZWQgJGxpY2Vuc2V0eXBlIgogICAgICAgIH0KICAgICAgICBlbHNlewogICAgICAgICAgICAkcmVzdWx0ID0gIlJlYWxWTkMgU2VydmVyIGlzIGxpY2Vuc2VkICRsaWNlbnNldHlwZSIKICAgICAgICB9CiAgICAgICAgV3JpdGUtT3V0cHV0ICRyZXN1bHQKICAgICAgICBleGl0IDAKICAgIH0KICAgIGVsc2V7CiAgICAgICAgJHJlc3VsdCA9ICJSZWFsVk5DIFNlcnZlciBpcyB1bmxpY2Vuc2VkIgogICAgICAgIFdyaXRlLU91dHB1dCAkcmVzdWx0CiAgICAgICAgZXhpdCAxCiAgICB9Cn0=" "${CLIENT_LIST_WINDOWS[@]}" fi if [ "$MAX_CLIENTS_LINUX" -gt 0 ]; then   execute_script"Linux""IyEvYmluL2Jhc2gKCmxpY2Vuc2VkPSJmYWxzZSIKbGljZW5zZXR5cGU9IiIKCmlmIFsgISAteCAvdXNyL2Jpbi92bmNzZXJ2ZXIteDExIF07IHRoZW4KCWVjaG8gIlJlYWxWTkMgU2VydmVyIGlzIG5vdCBpbnN0YWxsZWQiCglleGl0IDEKZmkKCmNsb3Vkam9pbmVkPSQodm5jc2VydmVyLXgxMSAtc2VydmljZSAtY2xvdWRzdGF0dXMgfCBncmVwIENsb3VkSm9pbmVkIHwgY3V0IC1mMiAtZCc6JyB8IHRyIC1kICcsJykKCiMgQ2hlY2sgb3V0cHV0IHRvIGRldGVybWluZSBpZiBSZWFsVk5DIFNlcnZlciBpcyBqb2luZWQgdG8gdGhlIGNsb3VkCmlmIFsgIiRjbG91ZGpvaW5lZCIgIT0gInRydWUiIF07IHRoZW4KCSMgUmVhbFZOQyBTZXJ2ZXIgaXNuJ3QgY2xvdWQgam9pbmVkLCBzbyBjaGVjayBmb3Igb2ZmbGluZSBsaWNlbnNlCgkKCWxpY2Vuc2VfaW5mbz0kKHZuY2xpY2Vuc2UgLWxpc3QpCgoJIyBDaGVjayBvdXRwdXQgdG8gZGV0ZXJtaW5lIGlmIFJlYWxWTkMgU2VydmVyIGhhcyBhbiBvZmZsaW5lIGxpY2Vuc2UKCWlmIFsgIiRsaWNlbnNlX2luZm8iID0gIk5vIG9mZmxpbmUgbGljZW5zZSBmb3VuZC4iIF07IHRoZW4KCQkjIFJlYWxWTkMgU2VydmVyIGlzbid0IG9mZmxpbmUgbGljZW5zZWQsIGJ1dCBtYXkgYmUgYSBWNyBTZXJ2ZXIgd2l0aCBhIFY2IG9mZmxpbmUgbGljZW5zZSBzbyBjaGVjayBmb3IgdGhhdAoJCWxpY2Vuc2VfaW5mbz0kKHZuY2xpY2Vuc2UgLWxlZ2FjeWxpc3QpCgkJCQkKCQlsaWNlbnNlX2luZm89JCh2bmNsaWNlbnNlIC1sZWdhY3lsaXN0KQoJCSMgLWxlZ2FjeWxpc3Qgd2lsbCBlaXRoZXIgcmV0dXJuIFY2IGxpY2Vuc2UgZGV0YWlscywgb3IgcHJpbnQgbm90aGluZyBlaXRoZXIgYmVjYXVzZSB0aGVyZSBpcyBubyBWNiBvZmZsaW5lIGxpY2Vuc2VkLy1sZWdhY3lsaXN0ZyBub3QgYmVpbmcgcmVjb2duaXNlZCAoVjYgU2VydmVyKQoJCWlmIFsgIiR7I2xpY2Vuc2VfaW5mb30iIC1ndCAwIF07IHRoZW4KCQkJbGljZW5zZWQ9InRydWUiCgkJCWxpY2Vuc2V0eXBlPSJvZmZsaW5lIgoJCWZpCgllbHNlCgkJbGljZW5zZWQ9InRydWUiCgkJbGljZW5zZXR5cGU9Im9mZmxpbmUiCglmaQplbHNlCglsaWNlbnNlZD0idHJ1ZSIKCWxpY2Vuc2V0eXBlPSJvbmxpbmUiCmZpCgppZiBbICIkbGljZW5zZWQiID0gInRydWUiIF07IHRoZW4KCWlmIFsgIiRsaWNlbnNldHlwZSIgPSAib25saW5lIiBdOyB0aGVuCgkJcmVzdWx0PSJSZWFsVk5DIFNlcnZlciBpcyBsaWNlbnNlZCAkbGljZW5zZXR5cGUiCgllbHNlCgkJcmVzdWx0PSJSZWFsVk5DIFNlcnZlciBpcyBsaWNlbnNlZCAkbGljZW5zZXR5cGUiCglmaQoJZWNobyAiJHJlc3VsdCIKCWV4aXQgMAplbHNlCglyZXN1bHQ9IlJlYWxWTkMgU2VydmVyIGlzIHVubGljZW5zZWQiCgllY2hvICIkcmVzdWx0IgoJZXhpdCAxCmZp""${CLIENT_LIST_LINUX[@]}" fi echo echo "-----   Results   -----" echo echo "Total no. RPort clients:          $TOTAL_CLIENTS" echo "No. connected RPort clients:      $TOTAL_CLIENTS_CONNECTED" echo "No. disconnected RPort clients:   $TOTAL_CLIENTS_DISCONNECTED" echo echo "No. of clients targeted:          $MAX_CLIENTS" echo "No. of Windows clients targeted:  $MAX_CLIENTS_WINDOWS" echo "No. of Linux clients targeted:    $MAX_CLIENTS_LINUX" echo echo "Clients with RealVNC Server:      $(( MAX_CLIENTS - $(grep -c 'RealVNC Server is not installed' $WORK_DIR/responses.txt)))" echo "Clients without RealVNC Server:   $(grep -c 'RealVNC Server is not installed' $WORK_DIR/responses.txt)" echo "Licensed RealVNC Servers:         $(grep -c 'RealVNC Server is licensed' $WORK_DIR/responses.txt)" echo "Unlicensed RealVNC Servers:       $(grep -c 'RealVNC Server is unlicensed' $WORK_DIR/responses.txt)" echo "Online licensed RealVNC Servers:  $(grep -c 'licensed online' $WORK_DIR/responses.txt)" echo "Offline licensed RealVNC Servers: $(grep -c 'licensed offline' $WORK_DIR/responses.txt)" exit_script "" 0

Query the RPort Audit log via API

Run the below script on a Linux computer to pull data from the RPort audit log. This could then be ingested into a SIEM such as Elastic. This script is not designed to be executed via RPort using the RPort script execution mechanism.

An RPort API token is required, which in this example has been created by user John and is saved into /home/user/rportapitoken.txt. The RPort server URL in this example is https://rportserver.com

#!/bin/bash
APITOKEN=`cat /home/john/rportapitoken.txt`

AUDITLOG=`curl -X 'GET' -H 'accept: application/json' -s -u john:$APITOKEN https://rportserver.com/api/v1/auditlog?sort=-timestamp`
echo $AUDITLOG | jq '.'
Was this article helpful?
3 out of 3 found this helpful

Comments

0 comments

Article is closed for comments.