Skip to content

Security Modes

Interaction to TACTIC by external services (including the web browser) all go through the TACTIC API. This is true for both Python adn Javascript implementations as well as connections through REST.

There are various levels of security access that restrict access to the TACTIC API. By default the TACTIC API has a large number of functions that can interact with TACTIC. However, many of these functions can have open access to TACTIC. More secure environments woill often wish to secure the API such that a small subset of functions.

There are 3 levels security

  1. Minimal
  2. Query
  3. Open

These can be set globally with in the TACTIC Config file. query

Minimal Mode

This is a very restricted user mode and is recommended for solutions that face the external internet. The only access to the server are through get_widget and execute_cmd.

The only 4 commands that can be used to intract with TACTIC are the following:

  • exeucute_cmd
  • get_widget
  • get_ticket
  • ping

This mode ensures that only strictly controlled commands and widget are executed from any external source.

Query Mode

(Query Methods allowed) - can only update through execute_cmd, but allowed to query

  • get_search_key
  • get_by_code
  • query

Open Mode

This mode provides full unrestricted access to the full API commands. It is not recommended to run this mode in production unless the solution is complete behind a firewall with access to only trusted users.

Restricted tables

By default, most tables in the TACTIC databases are available, however, there are a few tables that can only be searched using a special super user mode called Sudo. This super user mode can only be set in server Python code, ensuring that external API calls can never accidently query potentially sensitive data.

For example, from the api, even in Query mode, it is not possible to call:

server = TACTIC.get()
sobjects = server.query("sthpw/login")

This will raise a Permission Denied exception.

Even in server side Python code, the equivalent will raise an exception:

search = Search("sthpw/login")
sobjects = search.get_sobjects()

In order to get data from the restricted tables, you must place the service request in Sudo mode.

from pyasm.security import Sudo
sudo = Sudo()
try:
    search = Search("sthpw/login")
    sobjects = search.get_sobjects()
finally:
    sudo.exit()

This ensures that accidental queries to sensitive data from unwanted external sources is not possible because "sudo" mode can only be enabled from server side python. Also, the Sudo mode will exit when the variable goes out of scope (such as a function block).

The following stypes fall under the restricted tables:

  • sthpw/login_group
  • sthpw/login_in_group
  • sthpw/ticket
  • sthpw/transaction_log

Command key

Another level of security is to hide the class name execute by server.execute_cmd from end users. Basically, data about the command is stored in a key file and the name of the key is sent to the interface. The widget will use this key to call the command in the execute_cmd function.

For example:

In python

key = Widget.generate_command_key()

In html

<button class="but btn-default press_me" key="${key}">Press Me</button>

In behavior

<behavior class= "press_me">
    var key = bvr.src_el.getAttribute("key"):
    var kwargs = {}; // construct args needed for the command
    var server = TACTIC.get();
    server.execute_cmd(key, kwargs);
</behavior>

The key is generated on every instance of the interface and is tied to the user so it cannot by used by another user. The key has an expiry date which is the same as the login ticket that of the session that created the widget.

Some commands can only be run with a key. They have been designated as executable only through the use of key. This heps to prevent a particular command from being executed outside of a particular widget.

A command can be set up so that it requires a key to execute. This is is useful for commands that require enhanced security to execute.

class MyCmd(Command):

    def requires_key(self):
        return True

    def execute(self):
        # ... do something