Version: 21
restore

Contents

Introduction

This section describes an overview of Tachyon role based access control (RBAC) and its components and how to configure Tachyon RBAC.

This is not intended as an in-depth explanation of what RBAC is, but as a demonstration of how it's been implemented in Tachyon and how users can configure it programmatically.

The C# examples assume you're using Tachyon Consumer SDK and you have an instantiated instance of Tachyon connector class in an object called connector.

All SDK methods return the same class called ApiCallResponse. Inside the object of ApiCallResponse you'll find a property called ReceivedObject. That object is the actual data received from the API. In the following examples this detail is left out, stating that the returned object contains the data. For example, when we say that XYZ object contains certain data, this means the ReceivedObject contains that data, since that is always true.

On this page:

Basics of role based access control (RBAC)

Role-based access control is an access control mechanism defined around roles and privileges. This security model pivots around the concept or a Role. Users (called principals in Tachyon) can be assigned to a Role and it's through a Role they gain permissions to perform actions. Each element of Tachyon's security system leads back to a Role.

RBAC objects in Tachyon

Tachyon has several types of objects that are part of its RBAC system. This section briefly describes these object's description and purpose.

Principals

Principals are identical to users. They're not called users because the word 'user' is traditionally associated with a person. A principal is, from a technical standpoint, an Active Directory account which may be a user account or a computer account. It can also be an AD group.

Tachyon allows only principals authenticated through Windows authentication and known to Tachyon itself. Depending on the request, the Tachyon establishes the permissions of the calling principal by looking at the roles the principal is assigned to. By default, a fresh installation of Tachyon has a principal representing the user account installing it.

Roles

All permissions lead to roles. Principals must have roles assigned to them before using the system.

Permissions

A permissions is an ability to perform an operation on a securable type.

Securable Types

A Securable type is an object that can have permissions assigned to it. For example, Instructions can have permissions, as can Consumers and Management Groups. Security itself is an object principals need permissions to, so they can modify it, it will also have a securable type. If an element of Tachyon has security defined for it, it must have a securable type.

Instances

An Instance is one, specifc copy of an object of a given Securable Type. This can, for instance, be a single Instruction Set.

While most permissions work on Securable Types as a general thing, where if a Principal is assigned a Permission on a given Securable Type they can work with any object of that type, some Securable Types allow Permissions to be specified on just one given instance of a Securable Type object, giving a more granular control over access to that Securable Type.

As of version 4.2 only InstructionSet securable type supported instances.

Operations

An Operation (or Applicable Operation) represents the type of an action that can be performed on a securable type, like "Read" or "Write".

For example:

Marc (Principal) through his Global Questioners (Role) has Questioner (Applicable Operation) permission on Instructions (Securable type).

A Principal will have a specific permission on given securable type through a role the principal belongs to. This is the only way principals can obtain permissions and permissions are always for a specific operation on a given type.

To establish the full permission set of a given principal you have to combine all permissions from all the roles assigned to that principal.


Getting Permissions

You can retrieve permissions in several different ways, for example as a Principal, a Role or a Securable Type.

Some APIs perform checks for the calling user by pulling the user information from the HTTP request itself. Other APIs allow you to specify which object you want to get permissions for.

Getting permissions for a Principal

Getting all Permissions

Retrieving a principal's permissions is done using the account name (for example "somedomain\jane.doe") of that principal. When directly using the API, you have to encode that account name into base64 before sending it, while Consumer API SDK will do the encoding for you.

In general, any GET endpoint will require you to base64 encode the principal name, due to the fact that principal names can contain characters that are not allowed in URIs.

When you request permissions for a specific Principal, you will get permissions that Principal has stemming from any of their roles.

The following examples use the "somedomain\jane.doe" account.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/Permissions/Principal/c29tZWRvbWFpblxqYW5lLmRvZQ== will yield following response:

Return payload
[{
    "SecurableId": null,
    "SecurableName": null,
    "SecurableTypeId": 4,
    "SecurableTypeName": "Instrumentation",
    "RoleId": 4,
    "RoleName": "Infrastructure Administrators",
    "Allowed": true,
    "Operations": [{
        "PermissionId": 19,
        "OperationId": 11,
        "OperationName": "Read",
        "CreatedTimestampUtc": "2019-06-07T15:12:40.757Z",
        "ModifiedTimestampUtc": "2019-06-07T15:12:40.757Z"
    }]
},
{
    "SecurableId": null,
    "SecurableName": null,
    "SecurableTypeId": 12,
    "SecurableTypeName": "ProcessLog",
    "RoleId": 16,
    "RoleName": "Log Viewers",
    "Allowed": true,
    "Operations": [{
        "PermissionId": 61,
        "OperationId": 33,
        "OperationName": "Read",
        "CreatedTimestampUtc": "2019-06-07T15:12:44.13Z",
        "ModifiedTimestampUtc": "2019-06-07T15:12:44.13Z"
    }]
},
{
    "SecurableId": null,
    "SecurableName": null,
    "SecurableTypeId": 13,
    "SecurableTypeName": "SynchronizationLog",
    "RoleId": 16,
    "RoleName": "Log Viewers",
    "Allowed": true,
    "Operations": [{
        "PermissionId": 62,
        "OperationId": 34,
        "OperationName": "Read",
        "CreatedTimestampUtc": "2019-06-07T15:12:44.13Z",
        "ModifiedTimestampUtc": "2019-06-07T15:12:44.13Z"
    }]
},
{
    "SecurableId": null,
    "SecurableName": null,
    "SecurableTypeId": 14,
    "SecurableTypeName": "Component",
    "RoleId": 17,
    "RoleName": "Component Viewers",
    "Allowed": true,
    "Operations": [{
        "PermissionId": 64,
        "OperationId": 35,
        "OperationName": "Read",
        "CreatedTimestampUtc": "2019-06-07T15:12:44.13Z",
        "ModifiedTimestampUtc": "2019-06-07T15:12:44.13Z"
    }]
},
{
    "SecurableId": null,
    "SecurableName": null,
    "SecurableTypeId": 16,
    "SecurableTypeName": "InfrastructureLog",
    "RoleId": 16,
    "RoleName": "Log Viewers",
    "Allowed": true,
    "Operations": [{
        "PermissionId": 63,
        "OperationId": 39,
        "OperationName": "Read",
        "CreatedTimestampUtc": "2019-06-07T15:12:44.13Z",
        "ModifiedTimestampUtc": "2019-06-07T15:12:44.13Z"
    }]
}]

Use Permissions object inside the Tachyon connector instance.

Retrieving all Permissions for a specific Principal
permissions = connector.Permissions.GetForPrincipal("somedomain\\jane.doe");

"permissions" object will contain the same data you can see in the JSON response on the left.

Checking for a specific Permission

You can also retrieve permissions given Principal has on a particular Securable Type.

In the example below, we'll look at InstructionSet related permissions "somedomain\jane.doe" account has.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/Permissions/Principal/c29tZWRvbWFpblxqYW5lLmRvZQ==/Type/InstructionSet will yield following response:

Return payload
[
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 1,
        "RoleName": "Global Administrators",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 1,
                "OperationId": 1,
                "OperationName": "Viewer",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            },
            {
                "PermissionId": 2,
                "OperationId": 2,
                "OperationName": "Actioner",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            },
            {
                "PermissionId": 3,
                "OperationId": 3,
                "OperationName": "Questioner",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            },
            {
                "PermissionId": 4,
                "OperationId": 4,
                "OperationName": "Approver",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            }
        ]
    },
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 5,
        "RoleName": "Global Approvers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 5,
                "OperationId": 4,
                "OperationName": "Approver",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            }
        ]
    }
]

Use Permissions object inside the Tachyon connector instance.

Retrieving InstructionSet related permissions for a Principal
permissions = connector.Permissions.GetForPrincipalAndType("somedomain\\jane.doe", "InstructionSet");

"permissions" object will contain the same data you can see in the JSON response on the left.

If given Securable Type supports Instances, you can also check Principal's permissions on a specific instance.

In the example below we'll use a different account called "somedomain\john.doe" and check what permissions it has on Instruction Set with the Id of 1.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/Permissions/Principal/c29tZWRvbWFpblxqb2huLmRvZQ==/Type/InstructionSet/1 will yield following response:

Return payload
[
    {
        "SecurableId": 1,
        "SecurableName": "MySet",
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 30,
        "RoleName": "MySet Viewers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 137,
                "OperationId": 1,
                "OperationName": "Viewer",
                "CreatedTimestampUtc": "2020-01-02T12:04:04.963Z",
                "ModifiedTimestampUtc": "2020-01-02T12:04:04.963Z"
            }
        ]
    }
]

Use Permissions object inside the Tachyon connector instance.

Retrieving Principal's permissions to a specific instruction set
permissions = connector.Permissions.GetForPrincipalAndTypeAndInstance("somedomain\\john.doe", "InstructionSet", 1);

"permissions" object will contain the same data you can see in the JSON response on the left.

If given Principal has no permissions or doesn't have permissions on given Securable Type and/or instance, an empty collection is returned.

Getting permissions for a Role

You can retieve Role's permissions by using the role Id.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/Permissions/Role/16 will yield following response:

Return payload
[
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 12,
        "SecurableTypeName": "ProcessLog",
        "RoleId": 16,
        "RoleName": "Log Viewers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 61,
                "OperationId": 33,
                "OperationName": "Read",
                "CreatedTimestampUtc": "2019-11-07T13:14:56.673Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:56.673Z"
            }
        ]
    },
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 13,
        "SecurableTypeName": "SynchronizationLog",
        "RoleId": 16,
        "RoleName": "Log Viewers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 62,
                "OperationId": 34,
                "OperationName": "Read",
                "CreatedTimestampUtc": "2019-11-07T13:14:56.673Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:56.673Z"
            }
        ]
    },
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 16,
        "SecurableTypeName": "InfrastructureLog",
        "RoleId": 16,
        "RoleName": "Log Viewers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 63,
                "OperationId": 39,
                "OperationName": "Read",
                "CreatedTimestampUtc": "2019-11-07T13:14:56.673Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:56.673Z"
            }
        ]
    }
]

Use Permissions object inside the Tachyon connector instance.

Retrieving all permissions assigned to a Role
permissions = connector.Permissions.GetForRole(16);

"permissions" object will contain the same data you can see in the JSON response on the left.

You can also retrieve all permissions given Role has on a specific Securable Type.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/Permissions/Role/16/Type/ProcessLog will yield following response:

Return payload
[
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 12,
        "SecurableTypeName": "ProcessLog",
        "RoleId": 16,
        "RoleName": "Log Viewers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 61,
                "OperationId": 33,
                "OperationName": "Read",
                "CreatedTimestampUtc": "2019-11-07T13:14:56.673Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:56.673Z"
            }
        ]
    }
]

Use Permissions object inside the Tachyon connector instance.

Retrieving permissions that a Role has on a given Securable Type
permissions = connector.Permissions.GetForRoleAndType(16, "ProcessLog");

"permissions" object will contain the same data you can see in the JSON response on the left.

And for Securable Types that support Instances, you can also check Permissions on a specific Instace.

Here we'll get permissions for a custom Role that has been assigned a 'Viewer' permissions on an Instruction Set.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/Permissions/Role/30/Type/InstructionSet/1 will yield following response:

Return payload
[
    {
        "SecurableId": 1,
        "SecurableName": "Wszystko",
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 30,
        "RoleName": "MySet Viewers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 137,
                "OperationId": 1,
                "OperationName": "Viewer",
                "CreatedTimestampUtc": "2020-01-02T12:04:04.963Z",
                "ModifiedTimestampUtc": "2020-01-02T12:04:04.963Z"
            }
        ]
    }
]

Use Permissions object inside the Tachyon connector instance.

Retrieving permissions a Role has on a specific Instance of a Securable Type
permissions = connector.Permissions.GetForRoleAndTypeAndInstance(30, "InstructionSet", 1);

"permissions" object will contain the same data you can see in the JSON response on the left.

Getting permissions for a Securable Type

You can retrieve permissions granted on a Securable Type using the type's Id. This will return a collection of all permissions on a given type assigned to any of the Roles.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/Permissions/Securable/1 will yield following response:

Return payload
[
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 1,
        "RoleName": "Global Administrators",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 1,
                "OperationId": 1,
                "OperationName": "Viewer",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            },
            {
                "PermissionId": 2,
                "OperationId": 2,
                "OperationName": "Actioner",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            },
            {
                "PermissionId": 3,
                "OperationId": 3,
                "OperationName": "Questioner",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            },
            {
                "PermissionId": 4,
                "OperationId": 4,
                "OperationName": "Approver",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            }
        ]
    },
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 5,
        "RoleName": "Global Approvers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 5,
                "OperationId": 4,
                "OperationName": "Approver",
                "CreatedTimestampUtc": "2019-11-07T13:14:52.77Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:52.77Z"
            }
        ]
    },
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 6,
        "RoleName": "Global Questioners",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 21,
                "OperationId": 3,
                "OperationName": "Questioner",
                "CreatedTimestampUtc": "2019-11-07T13:14:54.96Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:54.96Z"
            }
        ]
    },
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 7,
        "RoleName": "Global Actioners",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 22,
                "OperationId": 2,
                "OperationName": "Actioner",
                "CreatedTimestampUtc": "2019-11-07T13:14:54.96Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:54.96Z"
            }
        ]
    },
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 8,
        "RoleName": "Global Viewers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 23,
                "OperationId": 1,
                "OperationName": "Viewer",
                "CreatedTimestampUtc": "2019-11-07T13:14:54.96Z",
                "ModifiedTimestampUtc": "2019-11-07T13:14:54.96Z"
            }
        ]
    },
    {
        "SecurableId": null,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 27,
        "RoleName": "ServiceNow ITSM Connect",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 136,
                "OperationId": 1,
                "OperationName": "Viewer",
                "CreatedTimestampUtc": "2019-11-07T13:18:05.767Z",
                "ModifiedTimestampUtc": "2019-11-07T13:18:05.767Z"
            }
        ]
    }
]

Use Permissions object inside the Tachyon connector instance.

Retrieving all Permisisons on a given Securable Type
permissions = connector.Permissions.GetForSecurableType(1);

"permissions" object will contain the same data you can see in the JSON response on the left.

You can also retrieve permissions granted on a specific Instance of a Securable Type.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/Securable/1/1 will yield following response:

Return payload
[
    {
        "SecurableId": 1,
        "SecurableName": null,
        "SecurableTypeId": 1,
        "SecurableTypeName": "InstructionSet",
        "RoleId": 30,
        "RoleName": "MySet Viewers",
        "Allowed": true,
        "Operations": [
            {
                "PermissionId": 137,
                "OperationId": 1,
                "OperationName": "Viewer",
                "CreatedTimestampUtc": "2020-01-02T12:04:04.963Z",
                "ModifiedTimestampUtc": "2020-01-02T12:04:04.963Z"
            }
        ]
    }
]

Use Permissions object inside the Tachyon connector instance.

Retrieving permissions assigned on a specific instance of a Securable Type
connector.Permissions.GetForSecurableTypeAndInstance(1, 1)

"permissions" object will contain the same data you can see in the JSON response on the left.

Helper APIs

Consumer API has a number of endpoints that are not directly involved with its RBAC system but instead provide various utility functions around the general principal and permission area.

Who am I?

You can ask the API to return the information about the user that is making the request. The API will examine the incoming request and retrieve name of the user from it, make sure that user is authenticated, and return information summary about the user, like user's principal name, SID, display name and email.

This endpoint is useful for systems that cannot assume that they are running under a particular account, like a browser or an application that runs in the context of launching user. In those cases this endpoint can be used to obtain the name of the user, which is then fed to the Permissions endpoint seen above in order to retrieve the permissions of the caller.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/PrincipalSearch/whoami will yield following response:

Return payload
{
    "PrincipalName": "Somedomain\\Jane.Doe",
    "ExternalId": "S-1-5-21-1202660629-789336058-1343024091-19970",
    "Email": "Jane.Doe@SomeDomain.com",
    "DisplayName": "Jane Doe",
    "Photo": null
}

Use PrincipalSearch object inside the Tachyon connector instance.

Who am I?
user = connector.PrincipalSearch.GetCurrentlyLoggedInUser();

"user" object will contain the same data you can see in the JSON response on the left.

Active Directory search

Because in order to add a Principal to Tachon you have to use a SID, Tachyon's Consumer API exposes nedpoints that help you look up users and establish their SIDs.

You can perform a search for Active Directory accounts whose common name or sAMAccountName contain given phrase. Details of what exact search is performed are beyong the scope of this page and depend on type of objects being searcher for, like users, groups and computers and whether your Tachyon installation is using GC or LDAP.

In the examples below we'll be looking for accounts that contain the phrase "Administrator". How you perform this search depends on your version of Tachyon.

Tachyon versions up to and including 4.1

You simply provide a base64 encoded search string and issue a GET request.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/PrincipalSearch/QWRtaW5pc3RyYXRvcg== will yield following response:

Return payload
[
	{
		"PrincipalName": "SomeDomain\\CSUserAdministrator",
		"ExternalId": "S-1-5-21-1202660629-789336058-1353024091-8145",
		"Email": null,
		"DisplayName": "CSUserAdministrator",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\CSVoiceAdministrator",
		"ExternalId": "S-1-5-21-1202660629-789336058-1343023091-8024",
		"Email": null,
		"DisplayName": "CSVoiceAdministrator",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Exchange Organization Administrators",
		"ExternalId": "S-1-5-21-1202660629-789336058-1343324091-6881",
		"Email": null,
		"DisplayName": "Exchange Organization Administrators",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Exchange Public Folder Administrators",
		"ExternalId": "S-1-5-21-1202660629-789336058-1340024091-7747",
		"Email": null,
		"DisplayName": "Exchange Public Folder Administrators",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Exchange Recipient Administrators",
		"ExternalId": "S-1-5-21-1202660629-789336058-1340024091-6913",
		"Email": null,
		"DisplayName": "Exchange Recipient Administrators",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Exchange View-Only Administrators",
		"ExternalId": "S-1-5-21-1202660629-789336058-1343024001-6999",
		"Email": null,
		"DisplayName": "Exchange View-Only Administrators",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Security Administrator",
		"ExternalId": "S-1-5-21-1202660629-789336058-1343021091-58611",
		"Email": null,
		"DisplayName": "Security Administrator",
		"IsGroup": true
	}
]

Use PrincipalSearch object inside the Tachyon connector instance.

Searching for principals in Active Directory
results = connector.PrincipalSearch.SearchForPrincipals("Administrator");

"results" object will contain the same data you can see in the JSON response on the left.

Tachyon versions 4.2 and newer

Here you have greater control over the search. A POST request should be used and in its payload you can specify, apart from the search string, number of results returned, sort column and order.

You can search for "user" and "group" object types and sort in either ascending (using "ASC") or descending order (using "DESC") on following columns: "cn", "mail", "sAMAccountName", "description", "objectSid", "displayName". Column names, object types and sorting direction string are not case sensitive.

You have to provide is the SearchText, so the text to search for, and at least one object type. Pagesize and sort are optional and if not provided will default to respectively 100 and ascending sorting on display name.

Direct Consumer API callC# code using Consumer SDK library

Making a POST request to https://my.tachyon.server/Consumer/PrincipalSearch with following payload:

Request payload
{
	"SearchText": "Administrator",
	"ObjectTypes": ["user", "group"],
	"PageSize": 100,
	"Sort": {
		"Column": "displayname",
		"Direction": "ASC"
	}
}

will yield following response:

Return payload
[
	{
		"PrincipalName": "SomeDomain\\CSUserAdministrator",
		"ExternalId": "S-1-5-21-1202660629-789336058-1353024091-8145",
		"Email": null,
		"DisplayName": "CSUserAdministrator",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\CSVoiceAdministrator",
		"ExternalId": "S-1-5-21-1202660629-789336058-1343023091-8024",
		"Email": null,
		"DisplayName": "CSVoiceAdministrator",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Exchange Organization Administrators",
		"ExternalId": "S-1-5-21-1202660629-789336058-1343324091-6881",
		"Email": null,
		"DisplayName": "Exchange Organization Administrators",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Exchange Public Folder Administrators",
		"ExternalId": "S-1-5-21-1202660629-789336058-1340024091-7747",
		"Email": null,
		"DisplayName": "Exchange Public Folder Administrators",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Exchange Recipient Administrators",
		"ExternalId": "S-1-5-21-1202660629-789336058-1340024091-6913",
		"Email": null,
		"DisplayName": "Exchange Recipient Administrators",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Exchange View-Only Administrators",
		"ExternalId": "S-1-5-21-1202660629-789336058-1343024001-6999",
		"Email": null,
		"DisplayName": "Exchange View-Only Administrators",
		"IsGroup": true
	},
	{
		"PrincipalName": "SomeDomain\\Security Administrator",
		"ExternalId": "S-1-5-21-1202660629-789336058-1343021091-58611",
		"Email": null,
		"DisplayName": "Security Administrator",
		"IsGroup": true
	}
]

Use PrincipalSearch object inside the Tachyon connector instance.

Retrieving 100 entries sorted by displayname
var searchParams = new ActiveDirectorySearchModel
{
	SearchText = "Administrator",
	ObjectTypes = new List<string> { "user", "group" },
	PageSize = 100,
	Sort = new SortSpec
	{
		Column = "displayname",
		Direction = "ASC"
	}
};

results = connector.PrincipalSearch.SearchForPrincipals(searchParams);

"results" object will contain the same data you can see in the JSON response on the left.

Retrieving Active Directory information about a specific account

You can also retrieve user's information by their principal name, though this endpoint only returns authenticated users who are also Principals in Tachyon (either directly or throught group membership).

This means that in order obtain information about somedomain\jane.doe using this endpoint, somedomain\jane.doe has to be a domain account that is either a Principal in Tachyon, or belongs to an Active Directory group that is a Principal in Tachyon.

When using the API directly the principal name has to be base64 encoded. Using the SDK encoding is not necessary because the SDK will perform the encoding internally.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/PrincipalSearch/user/c29tZWRvbWFpblxqYW5lLmRvZQ== will yield following response:

Return payload
[
    {
        "PrincipalName": "SomeDomain\\Jane.Doe",
        "ExternalId": "S-1-5-21-1202660629-789336058-1343024091-23842",
        "Email": "jane.doe@somedomain.com",
        "DisplayName": "Jane Doe",
        "IsGroup": false
    }
]

Use PrincipalSearch object inside the Tachyon connector instance.

Retrieve information about a principal from Active Directory
results = connector.PrincipalSearch.SearchForUser("SomeDomain\\Jane.Doe")

"results" object will contain the same data you can see in the JSON response on the left.

Retrieving members of an Active Directory group

You can ask Tachyon to retrieve members of an Active Directory group. This group does not have to be a principal in Tachyon for this functionality to work.

When using the API directly the group name has to be base64 encoded. Using the SDK encoding is not necessary because the SDK will perform the encoding internally.

In the example below we'll use an AD group called "Tachyon users" and retrieve its members.

Direct Consumer API callC# code using Consumer SDK library

Making a GET request to https://my.tachyon.server/Consumer/PrincipalSearch/GetMembers/VGFjaHlvbiB1c2Vycw== will yield following response:

Return payload
[
    {
        "PrincipalName": "SomeDomain\\Jane.Doe",
        "ExternalId": "S-1-5-21-1202660629-789336058-1343024091-23842",
        "Email": "jane.doe@somedomain.com",
        "DisplayName": "Jane Doe",
        "IsGroup": false
    },
    {
        "PrincipalName": "SomeDomain\\Meetra.Surnik",
        "ExternalId": "S-1-5-21-1202660629-789336058-1343024091-8631",
        "Email": "Meetra.Surnik@somedomain.com",
        "DisplayName": "Meetra Surnik",
        "IsGroup": false
    },
    {
        "PrincipalName": "SomeDomain\\Keiran.Halcyon",
        "ExternalId": "S-1-5-21-1202660629-789336058-1343024091-1138",
        "Email": "Keiran.Halcyon@somedomain.com",
        "DisplayName": "Keiran Halcyon",
        "IsGroup": false
    }
]

Use PrincipalSearch object inside the Tachyon connector instance.

Retrieving members of an Acive Directory group
results = connector.PrincipalSearch.GetGroupMembers("Tachyon users");

"results" object will contain the same data you can see in the JSON response on the left.

Configuring Tachyon's RBAC through the Consumer API

In this section we will look at configuring RBAC system emphasising operaitons on Principals, Roles and Permissions but also covering Securable Types and Operations later on.

Adding Principals from Active Directory

Adding Principals to Tachyon will be one of the first things you'll do after installing the system. A fresh installation of Tachyon (which in this context means an installation where there was no previous Master database or such database was dropped) will have two Principals - the account used to install the Tachyon Server (and create the database to be specific) and NT AUTHORITY\Network Service account.

These accounts have limited permissions so to properly use the system you should add more Principals. In order to add a principal to Tachyon you will need an External Id, also called SID, for an active directory account that you wish to add as a principal. Although you can obtain account details through various means, we've already seen Tachyon exposes endpoint that return this information and enables you to search for Active Directory accounts.

Here we will assume you already have the account details and focus on adding an account as a Principal to Tachyon.

In the example below we'll "SomeDomain\\Jane.Doe" account and add it to Tachyon.

To add an account as a Principal you will at the very least need to supply an ExternalId (SID) and Principal Name, though it is advised to also supply a Display Name. Also, unless you set the Enabled flag to true, the newly created account will be disabled by default.

Direct Consumer API callC# code using Consumer SDK library

Making a POST request to https://my.tachyon.server/Consumer/Principal with following payload:

Request payload
{
    "PrincipalName": "SomeDomain\\Jane.Doe",
    "ExternalId": "S-1-5-21-1202660629-789336058-1343024091-23842",
    "Email": "Jane.Doe@SomeDomain.com",
    "DisplayName": "Jane Doe",
    "IsGroup": false,
    "Enabled": true
}

will yield following response:

Return payload
{
    "Id": 3,
    "ExternalId": "S-1-5-21-1202660629-789336058-1343024091-23842",
    "PrincipalName": "SomeDomain\\Jane.Doe",
    "Email": "Jane.Doe@SomeDomain.com",
    "Enabled": true,
    "CreatedTimestampUtc": "2019-11-07T13:14:52.777Z",
    "ModifiedTimestampUtc": "2019-11-07T13:14:52.777Z",
    "SystemPrincipal": false,
    "DisplayName": "Jane Doe",
    "IsGroup": false
}


Use Principals object inside the Tachyon connector instance.

Adding a Principal to Tachyon
var payload = new Principal
{
    PrincipalName = "SomeDomain\\Jane.Doe",
    ExternalId = "S-1-5-21-1202660629-789336058-1343024091-23842",
    Email = "Jane.Doe@SomeDomain.com",
    DisplayName = "Jane Doe",
    IsGroup = false,
    Enabled = true
};

principal = connector.Principals.Add(payload)

"principal" object will contain the same data you can see in the JSON response on the left.

It is worth noting you cannot add a Principal with the same PrincipalName or ExternalId as another Principal that's already in the system, because both of those values must be unique.

Updating a Principal

Updating a Principal is very similar to adding one. You have to use a PUT verb instead of a POST if using the API directly, or Update method instead of Add if you're using the SDK. You also have to provide an Id that belongs to an existing principal.

One things to keep in mind is that you cannot modify system principals.

Again, you have to remember that ExternalId and PrincipalName must remain unique so you cannot change Principal's PrincipalName or ExternalId to one that matches another Principal's.

Configuring Roles

Roles are the pivotal point of an RBAC system.

Tachyon comes with a number of pre-defined roles, which should be sufficient to start with, but in time you will most likely create custome roles, either to restrict access to instruction sets or to cover permission sets required by specific roles within your organisation.

Adding, Editing and Removing a Role

First let's look at creating a Role. This can be done either in isolation, where just the role is created and any permissions must be assigned in subsequent call(s), or as a more complete package, where a Role is created along with a set of Permissions, which can include Management Groups.

Regardless of which approach is used, Principals have to be assigned separetely.

Assigning and unassigning Principals to Roles

Adding and removing Permissions to a Role

Assigning and unassigning Management Groups to a Role

Configuring Management Groups

Configuring Securable Types and Applicable Operations

Dealing with Operations