Can I create a non-admin user role with ability to review and terminate Vision Client sessions?

Is there a way to grant a role the ability to terminate Vision Client sessions without granting that role other gateway configuration permissions (i.e. without adding the role to the Gateway Config Roles setting)?

I have a client that wants to allow the site supervisors access to review and terminate client sessions as they are having some issue running into their concurrent client license limit, however we wouldn’t want to give those users broad configuration access.

I created a Supervisor role and added it to the Status Page Role(s) setting. That allows users with that role to see the gateway status, including connected Vision Clients, however the More button and the Terminate option are not present.

Ignition 7.9.10

No, the gateway doesn’t currently support such granular permissions. The ‘Terminate’ button is visible if the client has access to the config section of the gateway.

You could put a feature request on ideas.inductiveautomation.com, though.

If you’ve got at least one client open for supervisors, you could use system.util.sendMessage() and system.util.exit() to implement basically the same thing - just have a message handler on each client waiting for a terminate message, and run system.util.exit(). system.util.getSessionInfo() would give you the session ID(s) to terminate.

Or, if you dig through this forum, you could find access to the (unsupported and undocumented) internal classes used for the gateway, and use one of those to send a remote-terminate push message to the client; that’s as much of a hint as I’ll give.

4 Likes

@PGriffith, thanks for the suggestions. I was able to implement a basic client session management interface.

The basic setup is detailed below (for reference by others or for my own reference in the future)

  1. Create a client event script (message event) to accept client session termination request messages and trigger exit of the receiving client if the shared secret (string) included in the payload is correct.
# Name: ClientSessionTerminateRequest
def handleMessage(payload):
	if payload["sharedSecret"] == "<InsertRandomTextForSharedSecret>":
	  system.util.exit()
  1. Create a basic interface with the following components
    Button_ClearTable: Reset (clear) the data table
    Button_RefreshTable: Refresh (update) the data table
    Button_Terminate: Send request to terminate the selected client session.
    CheckBox_AutoRefreshTable: Used with a timer to enable/disable auto-refresh functionality.
    Timer_AutoRefresh: Used with a checkbox to implement auto-refresh functionality.
    Table_VisionClientSessions: used to show active client sessions and allow user to select rows

  2. Create actionPerformed script for Button_ClearTable:

headers = []
data = []
table = event.source.parent.getComponent('Table_VisionClientSessions')
table.data = system.dataset.toDataSet(headers, data)
  1. Create actionPerformed script for Button_RefreshTable:
table = event.source.parent.getComponent('Table_VisionClientSessions')
sessions = system.util.getSessionInfo()
table.data = system.db.toDataSet(sessions)
  1. Create propertyChange script for Timer_AutoRefresh:
event.source.value
if event.propertyName == "value":
	table = event.source.parent.getComponent('Table_VisionClientSessions')
	sessions = system.util.getSessionInfo()
	table.data = system.db.toDataSet(sessions)
  1. Link the “running” property of the timer to the “selected” property of the checkbox.

  2. Set the default state of the “selected” property on the checkbox to true.

  3. Create actionPerformed script for Button_Terminate*:

import sys

table = event.source.parent.getComponent('Table_VisionClientSessions')
rowIndex = table.selectedRow

if not (rowIndex >= 0):
	system.gui.messageBox("Please select a client session to terminate.","No selection made")
	sys.exit()

username = table.data.getValueAt(rowIndex, "username")
project  = table.data.getValueAt(rowIndex, "project")
address  = table.data.getValueAt(rowIndex, "address")
clientID = table.data.getValueAt(rowIndex, "clientID")

msg = """Are you sure you want to terminate the selected client session?
  username: %s
  project:  %s
  address:  %s
  clientID: %s
""" % (username, project, address, clientID)

if system.gui.confirm( msg, "Terminate selected client session?" ):
	results = system.util.sendMessage(
		 project = project
		,messageHandler = "ClientSessionTerminateRequest"
		,payload = {'sharedSecret': "<InsertRandomTextForSharedSecret>"}
		,scope = "C"
		,clientSessionId = clientID
	)

#	system.gui.messageBox(' '.join(results),"Client Session Terminate Request")

# Refresh table data
sessions = system.util.getSessionInfo()
table.data = system.db.toDataSet(sessions)
5 Likes