Chat now with support
Chat with Support

One Identity Safeguard for Privileged Sessions 6.2.0 - Creating custom Authentication and Authorization plugins

authenticate

The authenticate method performs the authentication of the session and returns a verdict that determines if SPS permits the connection to continue to the target server.

Example
def authenticate(self,
                 session_id,
                 protocol,
                 connection_name,
                 client_ip,
                 client_port,
                 key_value_pairs):
    return {
        'verdict': 'ACCEPT',
        'additional_metadata': 'my_metadata',
        'my_key': 'my_value',
    }

You must implement the authenticate method in the plugin.

TIP:

If you do not want to do anything in this method, include an empty method that returns the ACCEPT verdict.

Example
def authenticate (self):
    return {
        'verdict': 'ACCEPT',
    }

In addition, no gateway authentication has been performed by the plugin if the authenticate method returns:

  • None.
  • The dict {'verdict': 'NONE'}.
Input arguments

The order of the arguments does not make a difference, only their names do. Every argument is optional.

  • session_id

    Type: string

    Description: The unique identifier of the session.

    cookie

    Type: dictionary

    Description: The cookie returned by the previous hook in the session. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by one of the previous calls in this particular AA plugin. You can use the cookie to maintain the state for each particular connection or to transfer information between the different methods of the plugin. For an example that transfers information in the cookie between two methods, see Examples.

  • session_cookie

    Type: dictionary

    Description: You can use the session cookie to maintain global state between plugins for each particular connection. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by a previous plugin hook in the session.

  • connection_name

    Type: string

    Description: The name of the Connection policy that handles the client's connection request.

  • client_ip

    Type: string

    Description: A string containing the IP address of the client.

  • client_port

    Type: int

    Description: The port number of the client.

  • gateway_user

    Type: string

    Description: Contains the gateway username of the client if already available (for example, if the user performed inband gateway authentication), otherwise its value is None.

  • key_value_pairs

    Type: dictionary

    Description: A dictionary containing plugin-specific information (for example, it may include a token ID). This dictionary also contains any key-value pairs that the user specified. In the plugin, such fields are already parsed into separate key-value pairs. For details on how the user can provide such data during a connection, see "Integrating external authentication and authorization systems" in the Administration Guide.

  • protocol

    Type: string

    Description: The protocol used in the connection that the plugin is currently processing. Enter one of the following values: rdp, ssh, telnet.

  • target_server

    Type: string or None

    Description: Contains information about the target server if already available (for example, if the user performed inband gateway authentication), otherwise its value is None.

  • target_port

    Type: integer or None

    Description: Contains information about the target port if already available (for example, if the user performed inband gateway authentication), otherwise its value is None.

  • target_username

    Type: string or None

    Description: Contains information about the target username if already available (for example, if the user performed inband gateway authentication), otherwise its value is None.

Returned values

The method must return a dictionary with the following (required or optional) elements.

The required elements are:

  • verdict, which must contain one of the following returned values:

    • ACCEPT, which returns gateway_user and gateway_groups together.

    • NEEDINFO, which returns question.

    • DENY
    • NONE

The optional elements are:

  • cookie
  • session_cookie
  • additional metadata
  • gateway_user
  • gateway_groups
  • question

The elements in more detail:

  • verdict

    Type: string
    Required: yes

    Description: Must contain one of the following values:

    • ACCEPT:The authentication was successful, the client can continue the connection

      If the plugin returns both gateway_users and gateway_groups elements, it means that gateway authentication has been performed.

    • DENY: Reject the connection.
    • NEEDINFO: The authentication requires more information to be completed.
    • NONE: No gateway authentication was performed by the plugin.

    For example, the following sample code rejects the connection.

    Example
    return {'verdict': 'DENY'}

    • cookie

      Type: dictionary
      Required: no

      Description: The cookie returned by the previous hook in the session. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by one of the previous calls in this particular AA plugin. You can use the cookie to maintain the state for each particular connection or to transfer information between the different methods of the plugin. For an example that transfers information in the cookie between two methods, see Examples.

    • session_cookie

      Type: dictionary
      Required: no

      Description: You can use the session cookie to maintain global state between plugins for each particular connection. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by a previous plugin hook in the session.

    • additional_metadata

      Description: The value of this string will be stored in the Additional metadata column of the SPS connection database, and will be available on the SPS search interface.

    • gateway_user

      Type: string
      Required: no
    • gateway_groups

      Type: list
      Required: no

      Description: Optionally, the plugin can return the gateway_user and gateway_groups values. SPS will only update the gateway username and gateway groups fields in the connection database if the plugin returns the gateway_user and gateway_groups values. The returned gateway_user and gateway_groups values override any such attributes already available on SPS about the connection (which means that channel policy evaluations will be affected), so make sure that the plugin uses the original values appropriately.

      NOTE:

      If the plugin returns the gateway_user and gateway_groups values, you may have to configure an appropriate Usermapping Policy in the Connection Policy. If the plugin returns a gateway_user that is different from the remote user, the connection will fail without a Usermapping Policy. For details on Usermapping Policies, see "Configuring usermapping policies" in the Administration Guide.

      For example, the following sample code accepts the connection and sets the gateway_user and gateway_groups fields. (Naturally, you should write the plugin code that actually retrieves these data from the third-party system.) For details, see Examples.

      Example
      return {
          'verdict': 'ACCEPT', 
          'gateway_user': 'username-received-from-third-party', 
          'gateway_groups': [
              'usergroup1-received-from-third-party', 
              'usergroup2-received-from-third-party'
      	]
      }

    • question

      Type: tuple
      Required: no

      Description: A tuple that contains key-question pairs and optionally a third element to disable echoing. You can use it to request additional information from the client when using the NEEDINFO verdict in RDP, Telnet, and SSH connections. For example, the following sample code displays a prompt (in this case, Enter your token number) to the user. For details, see Examples.

      Example
      return {
          'verdict': 'NEEDINFO', 
          'question': ('token', 'Enter your token number: ')
      }

      If the optional third element is True, the answer will not be echoed to the client.

      TIP:

      Set the third element to True if the answer to the question is sensitive information (for example, a password).

      Example
      return {
          'verdict': 'NEEDINFO', 
          'question': ('token', 'Enter your token number: ', True)
      }

      Note that in SPS version 4.3.0 and 4.3.1, question was a dictionary. Starting with version 4.3.2, it is a tuple.

Requesting more information from the client

To request additional information from the client (for example, a one-time password from a token, or a ticket ID), the authenticate method may return the NEEDINFO verdict and the question tuple containing key-question pairs. The questions are asked from the user in a protocol-specific way and the authenticate method is called again with a key_value_pairs argument containing the answers in key-answer pairs, where the key belongs to the corresponding question. Alternatively, you can also use the cookie to supply additional information to the plugin.

authorize

The authorize method performs the authorization of the session and returns a verdict that determines if SPS permits the connection to continue to the target server. This method is executed only once. SPS executes the authorize method after the authentication method, and any inband gateway authentication or inband destination selection steps. As a result, the authorize method already has access to the IP address of the target server and the remote username (the username used in the server-side connection). You must implement the authorize method in the plugin.

TIP:

If you do not want to do anything in this method, include an empty method that returns the ACCEPT verdict. Otherwise, the connection will fail with the following log message: Calling Authorize hook of AA plugin failed..

Example
def authorize (self):
    return {'verdict': 'ACCEPT'}
Input arguments

The order of the arguments does not make a difference, only their names do. Every argument is optional.

  • session_id

    Type: string

    Description: The unique identifier of the session.

  • cookie

    Type: dictionary

    Description: The cookie returned by the previous hook in the session. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by one of the previous calls in this particular AA plugin. You can use the cookie to maintain the state for each particular connection or to transfer information between the different methods of the plugin. For an example that transfers information in the cookie between two methods, see Examples.

  • session_cookie

    Type: dictionary

    Description: You can use the session cookie to maintain global state between plugins for each particular connection. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by a previous plugin hook in the session.

  • connection_name

    Type: string

    Description: The name of the Connection Policy that handles the client's connection request.

  • client_ip

    Type: string

    Description: A string containing the IP address of the client.

  • client_port

    Type: int

    Description: The port number of the client.

  • gateway_groups

    Type: string list

    Description: The final gateway groups of the gateway user.

  • key_value_pairs

    Type: dictionary

    Description:

    A dictionary containing plugin-specific information (for example, it may include the username).

    This dictionary also contains any key-value pairs that the user specified when establishing the connection. In the plugin, such fields are already parsed into separate key-value pairs. For details on how the user can provide such data during a connection, see "Integrating external authentication and authorization systems" in the Administration Guide.

  • protocol

    Type: string

    Description: The protocol used in the connection that the plugin is currently processing. Enter one of the following values: rdp, ssh, telnet.

  • client_port

    Type: int

    Description: The port number of the client.

  • target_server

    Type: string or None

    Description: Contains information about the target server if already available (for example, if the user performed inband gateway authentication), otherwise its value is None.

  • target_port

    Type: integer or None

    Description: Contains information about the target port if already available (for example, if the user performed inband gateway authentication), otherwise its value is None.

  • target_username

    Type: string

    Description: The username SPS uses to authenticate on the target server.

Returned values

The method must return a dictionary with the following (required or optional) elements.

The required elements are:

  • verdict, which must contain one of the following returned values:

    • ACCEPT, which indicates that the authentication was successful and the client can continue the connection.

    • DENY, which rejects the connection.

The optional elements are:

  • cookie
  • session_cookie
  • additional metadata

The elements in more detail:

  • verdict

    Type: string

    Must contain one of the following values:

    • ACCEPT: The authentication was successful, the client can continue the connection.

    • DENY: Reject the connection.

    For example, the following sample code rejects the connection.

    Example
    return {
        'verdict': 'DENY'
    }
  • cookie

    Type: dictionary
    Required: no

    Description: The cookie returned by the previous hook in the session. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by one of the previous calls in this particular AA plugin. You can use the cookie to maintain the state for each particular connection or to transfer information between the different methods of the plugin. For an example that transfers information in the cookie between two methods, see Examples.

  • session_cookie

    Type: dictionary
    Required: no

    Description: You can use the session cookie to maintain global state between plugins for each particular connection. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by a previous plugin hook in the session.

  • additional_metadata

    Type: string
    Required: no

    Description: The value of this string will be stored in the Additional metadata column of the SPS connection database, and will be available on the SPS search interface.

session_ended

A session is the logical unit of user connections: it starts with logging in to the target, and ends when the connection ends. SPS executes the session_id hook when the session is closed. It is called exactly once for the same session.

TIP:

You can use this hook to send a log message related to the entire session or close the ticket related to the session if the plugin interacts with a ticketing system.

You must implement the session_ended method in the plugin.

Input arguments

  • session_id

    Type: string

    Description: The unique identifier of the session.

  • cookie

    Type: dictionary

    Description: The cookie returned by the previous hook in the session. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by one of the previous calls in this particular AA plugin. You can use the cookie to maintain the state for each particular connection or to transfer information between the different methods of the plugin. For an example that transfers information in the cookie between two methods, see Examples.

  • session_cookie

    Type: dictionary

    Description: You can use the session cookie to maintain global state between plugins for each particular connection. If this is the first call for that session, it is initialized as an empty dictionary, otherwise it has the value returned by a previous plugin hook in the session.

Returned values

This hook does not return values.

session_ended example

The following example formats every information received in the cookie into key-value pairs and prints a log message including this information into the log file.

Example
def session_ended(self, session_id, session_cookie, cookie):
    session_details = ','.join(['{0}={1}'.format(
        key, cookie[key]) for key in sorted cookie.keys()
    ])
    print("Session ended; session_id='{0}', session_details='{1}'".
        format(session_id, session_details))

Examples

The following example checks if the user has entered the string good as the token number. If the value of the token number is anything other than good, the plugin displays a prompt to the user up to three times. After three unsuccessful attempts, the plugin terminates the connection.

Example
def authenticate(self, key_value_pairs, cookie):
    if key_value_pairs.get('token') == "good":
        return {'verdict': 'ACCEPT'}

    cookie['cnt'] = cookie.get('cnt', 0) + 1
    if cookie['cnt'] > 3:
        return {'verdict': 'DENY'}

    return {'verdict': 'NEEDINFO',
            'question': ('token', 'Enter token number: '),
            'cookie': cookie
    }

The following example shows how to use the cookie to transfer data from the authenticate method to the session_ended method.

Example
import sys


class Plugin(object):

    def authenticate(self, session_id, cookie, protocol, 
    connection_name, client_ip, client_port, key_value_pairs):
        token = key_value_pairs.pop('token', None)

    # Accept the connection if the user provides a token number
    if token:
        # Write code here that validates the token number and 
        retrieves the username and usergroups of the user
        # We add the client_ip to the 'cookie' so it will be 
        available in the session_ended method as well
        return {
            'verdict': 'ACCEPT',
            'gateway_user': 'username-received-from-third-party',
            'gateway_groups': [
                'usergroup1-received-from-third-party',
                'usergroup2-received-from-third-party'],
            'additional_metadata': token,
            'cookie': {'client_ip': client_ip}
        }

    # Display a prompt to the user to request a token number
    else:
        return {
            'verdict': 'NEEDINFO',
            'question': ('token', 'Enter your token number: ')
        }

    def session_ended(self, session_id, cookie):
        session_details = ','.join([
            '{0}={1}'.format(key, cookie[key]) for key in 
            sorted(cookie.keys())
        ])

    # Send a log message when the session ends, including the 
    # client_ip address received in the cookie
    print("Session ended; session_id='{0}', session_details='{1}'".
        format(session_id, session_details))

Related Documents