Skip to Content
Primo RPA OrchestratorInstallationConfiguring RDP2 version 1.25.9.x

Configuring RDP2 version 1.25.9.x

Introduction

Starting with version 1.25.9.x, the WebApi and RDP2 services can interact using one of two methods:

  1. REST requests via the HTTP(S) protocol, which is the default method;
  2. Messages through a bus over WebSockets based on RabbitMQ.

Interaction between WebApi and RDP2 services using REST requests

Upon startup, the RDP2 service sends a notification about the used AddressFilter via the PUT /api/RdpSessions/UpdateAddressFilter request.

RDP2 service regularly queries all sessions that are relevant to it and, after processing, sends the state of these sessions back to the WebApi. To query sessions, GET /api/RdpSessions?addressFilter={filterString} is used. To send session states, PUT api/RdpSessions/UpdateConnectionStatuses request is used. In this same processing cycle, RDP2 service notifies the WebApi to check the idle periods for workers (robot machines) using GET api/RdpSessions/CheckNoRdpPeriods?addressFilter={filterString} request.

To terminate an RDP session, the RDP2 service sends a PUT api/RdpSessions/{id}/SetNeedForLogOffRDPSessionUser request.

Interaction between WebApi and RDP2 services via MQTT-over-WebSockets protocol

Upon startup or shutdown, the RDP2 service sends a notification in the message RdpServiceNoticeMessage with RdpServiceNotice inside:

/// <summary> /// Data sent by the RDP2 service to WebApi when starting or stopping the RDP2 service /// </summary> public class RdpServiceNotice { /// <summary> /// List of addresses serviced by the RDP2 service, all available addresses if the value is blank. /// </summary> public string AddressFilter { get; set; } /// <summary> /// IP address of the machine with the RDP2 service. /// </summary> public string Host { get; set; } /// <summary> /// Flag indicating start/stop of the RDP2 service. /// </summary> public bool IsStarted { get; set; } }

The WebApi service, upon receiving this message, saves the information in the Rdp2AddressFilters table and sends the full list of relevant RDP2 sessions to the bus in the RdpSessionDataMessage message, where each session is represented by the RdpSessionData class:

public class RdpSessionData { public int Id { get; set; } /// <summary> /// Name of the RDP user /// </summary> public string AdminName { get; set; } // TODO: why 2? /// <summary> /// Name of the RDP user /// </summary> public string UserName { get; set; } /// <summary> /// User password. /// </summary> public string Password { get; set; } /// <summary> /// IP address of the remote computer. /// </summary> public string Address { get; set; } /// <summary> /// Flag that is automatically raised if NeedNoRdpPause is set and there are no active robot sessions (Orchestrator robots) on the server. /// The flag is automatically reset after the pause duration (set in NoRdpPauseDurationInSeconds). /// </summary> public bool IsNoRdpPause { get; set; } /// <summary> /// Flag that is raised if a "pause" needs to be set on the machine without robot sessions (Orchestrator robots). /// The flag is automatically reset after the pause starts. /// </summary> public bool NeedNoRdpPause { get; set; } /// <summary> /// Duration of the pause without robot sessions (Orchestrator robots). /// </summary> public int NoRdpPauseDurationInSeconds { get; set; } = 60; /// <summary> /// Continue to support the RDP session (then nobody else will be able to connect via RDP) /// If you need to connect separately via RDP, it should be reset. /// </summary> public bool KeepRdpSession { get; set; } public bool UserProfileLoaded { get; set; } public int AuthenticationLevel { get; set; } public bool NegotiateSecurityLayer { get; set; } public bool EnableCredSspSupport { get; set; } public int DesktopWidth { get; set; } public int DesktopHeight { get; set; } public int ColorDepth { get; set; } public bool Connected { get; set; } /// <summary> /// Last date of switching true/false or false/true for Connected /// </summary> public DateTime? ConnectedChangedAt { get; set; } /// <summary> /// Last date of updating Connected (not necessarily true/false or false/true switch) /// </summary> public DateTime? ConnectedUpdatedAt { get; set; } public int WorkerId { get; set; } public int? RdpPort { get; set; } /// <summary> /// Forcefully reconnect the session even if it is connected. /// Only for Windows RDP. /// </summary> public bool? ForceKeepRdpSession { get; set; } }

To enable or disable an RDP session, the WebApi service sends the RdpSessionDataMessage message with one session in the body to the bus.

The RDP2 service receives RdpSessionDataMessage messages from the bus and stores them in its internal cache as relevant RDP sessions. The RDP2 service regularly checks the status of sessions from the internal cache and stops or starts them as needed. At the end of each check cycle, the RDP2 service sends the RdpSessionStatusesMessage message with the status of each serviced session to the bus:

/// <summary> /// Information about the RDP session status. /// </summary> public sealed class RdpSessionStatus { /// <summary> /// ID of the session. /// </summary> public int SessionId { get; set; } /// <summary> /// Whether the session is connected. /// </summary> public bool Connected { get; set; } /// <summary> /// Time of connection change. /// </summary> public DateTime ConnectedChangedAt { get; set; } /// <summary> /// Time of connection update. /// </summary> public DateTime ConnectedUpdatedAt { get; set; } }

and the message RdpCheckPausePeriodsMessage with its AddressFilter.

To terminate an RDP session, the RDP2 service sends the RdpSetNeedForLogoffMessage message with the session ID.

To enable interaction through the bus, RabbitMQ, NGINX, WebApi, and RDP2 services need to be configured.

Configuring RabbitMQ

On the server where RabbitMQ is running, execute the following commands with administrator privileges (for Windows, first navigate to the directory C:\Program Files\RabbitMQ Server\rabbitmq_server-Version\sbin):

rabbitmq-plugins enable rabbitmq_mqtt rabbitmq-plugins enable rabbitmq_web_mqtt

If using a firewall, open port tcp/15675, which is used for MQTT-over-WebSockets.

Configuring NGINX

To proxy client requests to the RabbitMQ server’s MQTT service, add the following (bolded text) to the NGINX configuration file (nginx.conf):

http { ... upstream mqtt { server <i>&lt;IP or name of the RabbitMQ server&gt;</i>:15675; } ... server { ... location /mqtt/ { proxy_pass http://mqtt; rewrite ^/mqtt/(.*)$ /$1 break; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } ... } }

After making changes to the nginx.conf file, check the configuration:

nginx -t

And restart the NGINX service if there are no errors.

Configuring the WebApi service

The WebApi service can interact with the RDP2 services simultaneously using both methods: REST requests and through a message bus, depending on which method is configured for the specific RDP2 service.

To enable interaction through the bus, add Mqtt section to the appsettings.XXX.json file:

{ ... }, <b> "Mqtt": { "Url": "wss://<i>&lt;IP or name and port of the NGINX server&gt;</i>/mqtt/ws", "Username": "<i>&lt;RabbitMQ user&gt;</i>", "Password": "<i>&lt;(encrypted) RabbitMQ user password&gt;</i>" }, ... }

Configuring the RDP2 service

To enable interaction through the message bus, add Mqtt section to the appsettings.XXX.json file:

{ ... }, <b> "Mqtt": { "Url": "wss://<i>&lt;IP or name and port of the NGINX server&gt;</i>/mqtt/ws", "Username": "<i>&lt;RabbitMQ user&gt;</i>", "Password": "<i>&lt;(encrypted) RabbitMQ user password&gt;</i>" }, ... }

If the Mqtt section is absent or the Url parameter is blank, interaction through the message bus will be disabled.

Last updated on