Access Director Agent

The Access Director Agent distributes Access Control information (passwords) to all subscribed agents in the OCS instance. See the main article on Access Control, and the Agent Description below.

usage: agent.py [-h] [--config-file CONFIG_FILE]

Agent Options

--config-file

AccessDirector config file.

Configuration File Examples

OCS Site Config

To configure the Access Director Agent we need to add an AccessDirector block to our ocs configuration file. Here is an example configuration block using all of the available arguments:

{'agent-class': 'AccessDirector',
 'instance-id': 'access-dir',
 'arguments': ['--config-file', '/config/access-director.yaml']}

Docker Compose

The Access Director Agent can also be run in a Docker container. An example docker-compose service configuration is shown here:

ocs-access-dir:
    image: simonsobs/ocs:latest
    hostname: ocs-docker
    environment:
      - LOGLEVEL=info
      - INSTANCE_ID=access-dir
    volumes:
      - ${OCS_CONFIG_DIR}:/config:ro

Access Director Configuration File

The format is described below, but for a browsable schema see ocs.access.AccessDirectorConfig.

Here is an example configuration file:

# Policy file for OCS Access Directory Agent

passwords_block_default_hashfunc: none
distrib_hashfunc: md5

passwords:
  - default: true
    password_4: 'superuserPassword!'
  - agent_class: 'FakeDataAgent'
    instance_id: '!faker4'
    password_2: 'fake2ser'
  - instance_id: 'faker4'
    password_2: 'specialLevel2'
    password_3: 'speciallevel3'

exclusive_access_blocks:
  - name: "the-fakers"
    password: "lockout-test"
    grants:
    - instance_id: "faker4"
      lock_levels: [1,2,3]
      cred_level: 1
    - instance_id: "faker*,!faker4"
      lock_levels: [3]
      cred_level: 3

The passwords entry is a list of password assignment blocks, which define passwords that should grant clients certain credential levels on certain agents.

The syntax of the assignment blocks is described in ocs.access.AccessPasswordItem.

Examples

Example 1 – set the level (1,2,3,4) passwords for all agents to (‘’, ‘special2’, ‘special3’, ‘superuser’):

passwords:
  - default: true
    password_1: ''
    password_2: 'special2'
    password_3: 'special3'
    password_4: 'superuser'

Example 2 – like Example 1 except that any agent with the class “FakeDataAgent” will have level 2 password set to ‘fake2’:

passwords:
  - default: true
    password_1: ''
    password_2: 'special2'
    password_3: 'special3'
    password_4: 'superuser'
  - agent_class: FakeDataAgent
    password_2: 'fake2'

Example 3 – like Example 2 except that the agent with instance_id=danger4 will not be granted any special level 2 or 3 access passwords. To do this, it is necessary to negatively match on instance_id – the default: true block can only apply to everything:

passwords:
  - default: true
    password_1: ''
    password_4: 'superuser'
  - instance_id: '!danger4'
    password_2: 'special2'
    password_3: 'special3'
  - agent_class: FakeDataAgent
    instance_id: '!danger4'
    password_2: 'fake2'

exclusive_access_blocks

The exclusive_access_blocks entry is a list of access grant blocks. Each block must at least have a (unique) “name” entry, and a list of GrantConfigItem. Each GrantConfigItem targets some set of agent instances (using the default / agent_class / instance_id keys in the same way that ocs.access.AccessPasswordItem does). The cred_level declares what level to give the grantee, on the targeted instances. The lockout_levels is a list of Credential Levels to lock out, during this grant.

The additional settings items are:

  • passwords_block_default_hashfunc: name of the hash function to assume for passwords provided in the “passwords” block. (Default: “none”, meaning they are in cleartext.)

  • distrib_hashfunc: hashfunc to use, instead of cleartext, when distributing passwords to agents. (Does not affect passwords that were provided already hashed – those are distributed in hashed form, correctly annotated with the hashfunc declared for them.)

Description

The role of this Agent is to distribute Access Control information to Agent Instances and Clients in the OCS instance. In an OCS there will normally be zero or one instance of the Access Director (but it’s possible to set up multiple instances, and have different agents attuned to different Access Directors).

The agent configuration is provided through the Access Config File, the path to which is a command-line parameter. The manager process distributes access information to agents on a special feed (...feeds.controls). The task reload_config may be used to trigger a reload of the config file. If there are syntax errors in the config file, this will normally cause the reload to be ignored and the existing configuration to persist.

Two “special access points” are exposed by the Access Director. The agent_poll method is used by agents to request an update of their current access information; they will normally do this when they connect or reconnect to crossbar.

The request_exclusive access point is used by clients that wish to establish an Exclusive Access Lock. The client would provide the name of the access block, and a password (if defined). The Agent then returns to that client a randomly generated password that the client can use to talk to all agents covered by the grant. Starting then, and until the grant expires or is released, the Agent distributes updated access information to all agents that reflects the new access rules – i.e. special access levels, granted based on that password, and also any lock-outs that are associated with the grant.

Agent API

class ocs.agents.access_director.agent.AccessDirector(agent, config_file)[source]

Agent for distributing Access Control information to all Agents in a system.

manager()[source]

Process - Update the main access control feed with new access information. This occurs in response to agent queries, or if new grants require updates to access.

The session.data encodes information about any active exclusive grants. The entry for grants contains a list of :class:<AccessGrant> entries. It looks like this:

'grants': [
  {
    "name": "fake-subsystem",
    "expire_at": 1771356419.8087718,
    "grantee": "test-grant.py",
    "rules": [
      {
        "hashed_pass": {
          "hash": "md5",
          "value": "03ba0072e0d32376"
        },
        "cred_level": 2,
        "scope_spec": {
          "default": false,
          "agent_class": "FakeDataAgent",
          "instance_id": null
        },
        "lockout_id": "fake-subsystem",
        "lockout_owner": "test-grant.py",
        "lockout_levels": [
          2,
          3
        ]
      },
      {
        "hashed_pass": {
          "hash": "md5",
          "value": "03ba0072e0d32376"
        },
        "cred_level": 1,
        "scope_spec": {
          "default": true,
          "agent_class": null,
          "instance_id": null
        },
        "lockout_id": "fake-subsystem",
        "lockout_owner": "test-grant.py",
        "lockout_levels": [
          3
        ]
      }
    ]
  }
]
reload_config()[source]

Task - Reload access config file.

agent_poll(instance_id, agent_class)[source]

Special access point. This is used for agents to request an announcement of their password rules on the control feed. The instance_id and agent_class arguments must both be specified (and not None). Returns True if arguments are sufficiently valid and request was slated; otherwise False.

request_exclusive(grant_name=None, password=None, action=None, expire_at=None, grantee=None, strict=None)[source]

Special access point. Request, renew, or release an exclusive access grant.

Parameters:
  • grant_name (str) – Name of the grant, to match an entry in the “grant-blocks” section of the config file.

  • password (str) – The password, to be checked against the password specified in the grant block of the config.

  • action (str) – One of “acquire”, “renew” or “release”.

  • expire_at (float) – Unix timestamp for the desired expiry time of the grant.

  • grantee (str) – A string representing the client that has requested the lock. When passed with “acquire”, it is stored for distribution to clients so they can explain who has locked them out.

  • strict (bool) – If True, reject all requests except acquire when a grant is inactive, renew when a grant is active, and release when a grant is active.

Returns:

A dict with useful info.

On error, the dict has only an entry “error” with an error message in it.

On success, the returned dict has at least the items ‘grant_name’ (which matches the requested grant_name) and ‘message’; the ‘message’ is just “grant acquired” / “grant renewed” / “grant released”. It also has the ‘step’ at which this event took effect in the director.

Additionally, if the ‘action’ is ‘acquire’ or ‘renew’ then the dict will include an entry ‘expire_at’ with the unix timestamp that the grant will be cancelled automatically. This timestamp may be earlier (but not later) than the time requested with the expire_at parameter.

If the action is ‘acquire’, then the dict also has an entry ‘password’, containing the password client should use to access the exclusive access targets for the duration of the access grant.