Permissions
Toolkit permissions are fairly complex. It’s best to start with reading the Entities and Policy Taxonomy sections. Then you can either read on with the Policies Explained, if you prefer formal documentation, or move to Permission Scenario if you prefer learning through examples. You can also view the Tips section at the end of the page.
Entities
Type |
Description |
---|---|
Organization |
The top-level concept that pertains to permissions. The root of every Toolkit entity is an organization. By
default, ServiceNow automatically get a user created under the |
User |
An entity, uniquely identified via an email, that can authenticate in the system via various authentication methods including email/password, single sign-on and tokens. In Toolkit, aside from default permissions on user creation, permissions are provided via the concept of roles. |
Account |
The children entities of organizations. They can be subspaced. Their children are roles. Subspaced accounts, data, jobs and registries are tied to accounts. |
Role |
Live under accounts. They associate users to policies. |
Policy |
A rule that gives rights over Toolkit resources. |
Data |
A Toolkit data storage. |
Job |
A task running inside Toolkit. |
Excluding policy, these concepts are resource types on which Toolkit policies can be applied.
All those entities have a matching CLI command.
Policy Taxonomy
- Policy:
<action>@<resource>
. action:
(<action type>:<action verb>)|*
A wildcard means all permissions on all resource types.action type:
user|account|role|policy|data|job|registry|*
The wildcard means all of them.- action verb:
get|set|new|*
. The wildcard means all of them. get: Read permission.
set: Write permission. In many situations, having a “set” permission alone is insufficient, to perform a write operation, because one can hardly write to things that can’t be seen. Hence, the “get” permissions may be needed.
new: Create permission.
- action verb:
resource:
<organization id>:<resource type>:<resource id>[:<resource type>:<resource id>]
It is possible to use wildcards. Eg.:snow:user:*
means all users under the snow organization.snow:*
means all entities under snow.
- Policy:
The taxonomy described here is the one supported by Toolkit. Policies are very liberal and it is possible
to create policies unrelated to that taxonomy, as long as they are more or less of the form <left>@<right>
.
For instance, the following policy can be created but would have no inherent impact on Toolkit: potato@kitchen
.
However, user developped applications can look it up and take decisions based on it.
Note
There is no delete action. Toolkit resources are permanent.
Policies Explained
All Toolkit entities live in a hierarchy. At the top lives the organization concept. This one is only manageable by Toolkit administrators. Under organization live users and accounts. Under accounts live more accounts, roles, jobs, data and registries. Each of these instances live in a single account. Users can have multiple roles. Finally, policies are bound to roles.
Putting it all together, we have users who have roles. Their roles have policies <action>@<resource>
. In
plain English, we can say that those users can perform the action on the resource.
Policies are additive. The sum of the policies in the roles in which your user is makes up your permissions.
Expirable Policies
When policies are created, an expiration can be set on them either at a target datetime with the --expiration
flag or the --duration
flag.
Expired policies are not pruned automatically. They are still listed, but don’t take effect.
Accounts, Roles and Policies
When an account is created, it automatically comes up with two roles: admin and user. The creator is automatically added to the admin role and has all permissions on the account and its sub resources. Those permissions are shareable by default. Example.:
eai role policy ls snow.account:demo.admin
policy action expression shareable expiration
18438923-0ead-4dbe-a62a-7bd6309faa35 * 34545543-8382-4437-a68b-18414701dec2:account:69321629-0990-4072-83c5-ed1050464df1:* true -
18438923-0ead-4dbe-a62a-7bd6309faa35 * 34545543-8382-4437-a68b-18414701dec2:account:69321629-0990-4072-83c5-ed1050464df1 true -
We see that this role gives all permissions, as denoted by the *
under action
on the account itself (the 2nd line) and
all resources under it (the 1st line, the expression ending with :*
).
No users are added to the user role. It’s automatically created for convenience with get (read) permission on the account itself and its sub resources. Those permissions are not shareable by default. Here is an example of its default policies:
eai role policy ls snow.account:demo.user
policy action expression shareable expiration
18438923-81f3-4b08-8561-8e56c2ee37a6 *:get 34545543-8382-4437-a68b-18414701dec2:account:69321629-0990-4072-83c5-ed1050464df1:* false -
18438923-81f3-4b08-8561-8e56c2ee37a6 *:get 34545543-8382-4437-a68b-18414701dec2:account:69321629-0990-4072-83c5-ed1050464df1 false -
We see that this role gives get permissions, as denoted by the *:get
under action
on the account itself (the 2nd line) and
all resources under it (the 1st line, the expression ending with :*
).
Warning
When a user is created, it automatically gets an associated account. These accounts are special. They don’t start with any roles in them. They are bound to their owner and Toolkit internals grants their owner all the permissions over these accounts. To use them, it’s best to create sub accounts, into which the regular admin and user roles will be created and where users will be able to adjust policies.
To view the policies tied to your user, run eai user policy ls
.
Multiple Rules Under the Same Policy ID
The command to create policies allows for the creation of many rules at once. In this case, they will all live under the same policy id but be listed as different rules for readability. Example.:
$ # because URNs tend to be very long, this example first export it to a variable to make the command more succint.
$ export URN=34545543-8382-4437-a68b-18414701dec2:account:3e441dbe-ec2a-46d4-98bb-968d9f1e3c85:data:d6404ee5-2b69-4284-ad16-cec8d75ea546
$ eai role policy new snow.account:patate.admin data:get@$URN data:set@$URN
id name statements.actions statements.resources shareable expiration
54435345-15b7-453f-94d3-9d26f373c073 [data:get] [34545543-8382-4437-a68b-18414701dec2:account:3e441dbe-ec2a-46d4-98bb-968d9f1e3c85:data:d6404ee5-2b69-4284-ad16-cec8d75ea546] false -
54435345-15b7-453f-94d3-9d26f373c073 [data:set] [34545543-8382-4437-a68b-18414701dec2:account:3e441dbe-ec2a-46d4-98bb-968d9f1e3c85:data:d6404ee5-2b69-4284-ad16-cec8d75ea546] false -
$ eai role policy ls snow.account:patate.admin
policy action expression shareable expiration
54435345-15b7-453f-94d3-9d26f373c073 data:get 34545543-8382-4437-a68b-18414701dec2:account:3e441dbe-ec2a-46d4-98bb-968d9f1e3c85:data:d6404ee5-2b69-4284-ad16-cec8d75ea546 false -
54435345-15b7-453f-94d3-9d26f373c073 data:set 34545543-8382-4437-a68b-18414701dec2:account:3e441dbe-ec2a-46d4-98bb-968d9f1e3c85:data:d6404ee5-2b69-4284-ad16-cec8d75ea546 false -
In the previous example, two policies were explicitly created within the same command. For convenience, an advanced
syntax that does the cartesian product on the action and resource parts of the policy is applied. Each
action and resource need to be split with a +
character. Here is an example where the equivalent
policies as above are created. Notice how the immediate reply from the policy creation command differs.
$ eai role policy new snow.account:patate.admin "data:get+data:set@$URN"
id name statements.actions statements.resources shareable expiration
54334523-da26-4017-b75f-dc5abf350f4c [data:get data:set] [34545543-8382-4437-a68b-18414701dec2:account:3e441dbe-ec2a-46d4-98bb-968d9f1e3c85:data:d6404ee5-2b69-4284-ad16-cec8d75ea546] false -
$ eai role policy ls snow.account:patate.admin
policy action expression shareable expiration
54334523-da26-4017-b75f-dc5abf350f4c data:get 34545543-8382-4437-a68b-18414701dec2:account:3e441dbe-ec2a-46d4-98bb-968d9f1e3c85:data:d6404ee5-2b69-4284-ad16-cec8d75ea546 false -
54334523-da26-4017-b75f-dc5abf350f4c data:set 34545543-8382-4437-a68b-18414701dec2:account:3e441dbe-ec2a-46d4-98bb-968d9f1e3c85:data:d6404ee5-2b69-4284-ad16-cec8d75ea546 false -
Warning
The pitfall with these policies is that, even though they are listed over many lines, they are the same policy.
Quickly looking at the previous example, someone may want to remove the data:set
permission, run the removal
command on the policy id, and end up deleting data:get
as well because they were bound to the same policy.
Default Policies of the snow
Organization
Warning
This is about users joining the snow
organization. Users joining other organizations may get different policies.
Default policies are created when users are added to organizations. For snow
, there are three of them.
1. Policies affecting the user
The
user:set
policy is created, having both the user as the source and target, allowing the user to set the associated name.A policy is created to allow the user to do anything in the associated account.
Example:
% eai user policy ls
policy action expression
12312312-ff56-404b-b320-c7cbaf0abe38 user:set 89089089-8382-4437-a68b-18414701dec2:user:12312312-c35f-4ce8-882a-dd289889bd5d
56756756-a4b3-41c0-96de-a328f2f558a7 * 89089089-8382-4437-a68b-18414701dec2:account:23423434-1714-46b8-90f5-4b3a2afaac5c
56756756-a4b3-41c0-96de-a328f2f558a7 * 89089089-8382-4437-a68b-18414701dec2:account:23423434-1714-46b8-90f5-4b3a2afaac5c:*
2. snow.user
role
The user is added to the snow.user
role. This gives the permission to get the organization (last policy in the
example), to create a new account (the second to last in the example), and to get different types of resources under the
organization except listing them.
Example:
$ eai role policy ls snow.user
policy action expression
53409845-9fc0-47d7-b476-0cf7c688adc6 *:get 89089089-8382-4437-a68b-18414701dec2:registry:*
54321981-7080-41e2-86ef-a4c20cbb7759 *:get 89089089-8382-4437-a68b-18414701dec2:policy:*
18930147-f7a9-4cc2-b534-de7ead4619d5 *:get 89089089-8382-4437-a68b-18414701dec2:role:*
12386798-5477-483b-977f-a8eecee1973e *:get 89089089-8382-4437-a68b-18414701dec2:team:*
12389876-aea6-46bb-8bb2-664e93f0dc48 *:get 89089089-8382-4437-a68b-18414701dec2:user:*
84781457-4e21-4faa-a074-886b8f6aeba3 account:new 89089089-8382-4437-a68b-18414701dec2
87774466-2d2f-4dca-9a6e-f1c7a4d7749e *:get 89089089-8382-4437-a68b-18414701dec2
Note
registry:*
and policy:*
are Toolkit bugs and don’t do anything.
3. snow.everyone
role
The user is added to the snow.everyone
team. This group is intended to let Toolkit users openly share resources with
the whole organization. Anyone willing to share resources with the organization is welcome to create the proper policies
between that team and those resources.
Hint
A convenient way to share resources with the snow.everyone
team is to create an account for yourself and that
purpose. (e.g.: snow.alice.shared
) Then you can add snow.everyone
to that account user role. (Following the
same example, that would be snow.alice.shared.user
.)
Examples
To make the commands simpler, IDs are represented as ${<TYPE>_ID}
.
1. Allowing a Role to Connect to A Job
eai role policy new snow.account_a.role_r job:get@${ORG_ID}:account:${ACCOUNT_ID}:job:${JOB_ID}
Users in the snow.account_a.role_r
can connect (get
permission) to the job
${ORG_ID}:account:${ACCOUNT_ID}:job:${JOB_ID}
.
You can also use the eai cli to substitute the URN.
eai role policy new snow.account_a.role_r job:get@$(eai job get ${JOB_ID} --field urn)
Hint
This later notation will be used for the following examples.
2. Allowing a Role to Pull Docker Images from a Registry
eai role policy new snow.account_a.role_r registry:get@$(eai account get org.account_b --field urn)
3. Allowing a Role to Read from a Data
eai role policy new snow.account_a.role_r data:get@$(eai account get org.account_b.data_d --field urn)
Permission Scenario
The following series of scenarios will illustrate some of the most fundamental concepts behind the Toolkit.
We will start with the addition of a new organization
to the toolkit, and make our way step by step to project
shared by multiple user profiles who each have different levels of permission accesses.
Step 0: A new organization is created
This step can only be taken by a Toolkit superadmin. It creates the root object for your organization
.
It will also create two children roles
under the organization
:
role
adminrole
user
The Tookit superadmin is automatically assigned to the role admin for the new organization
. This is transferable
later on to the administrator in the organization
. When a user
is assigned a role
, we say that the user
becomes a member
of that role
.
Step 1: A first user is added to the organization
A user
is a resource that can be added as a child to an organization
or as a member
to a team
(more on teams later). Only users with the role
of admin on the organization
can invite new users. In our scenario, since the EAI_superadmin is still the only administrator for
the acme organization
, he or she will have to invite a new user
from that organization
.
This is done with the eai user invite
command. To add a new user
to an organization
,
all that is needed is an email address.
eai user invite <mail@domain> --organization <organization>
Adding a user
to the organization
results in a few things happening:
The
user
is added as a child to theorganization
and as amember
of theuser
role for thatorganization
. Or it can be renamed thereafter with the command$ eai user set <user id> --name <new name>
A “sandbox”
account
is added as a child to theorganization
.The
user
will be granted all set and get permissions on that “sandbox”account
. This is the user personalaccount
. It can be renamed afterward through$ eai account set <account id> --name <new name>
For the purpose of our scenario, we have added the user
alice and named her sandbox account
alice_sandbox. Everything is ready for Alice to start using the toolkit, except that she hasn’t
logged in yet… Let’s have her login.
Step 2: Starting new project(s)
Alice is now ready to start setting up new projects. On the toolkit, the concepts of “project” and “account” are completely interchangeable. The terminology account was chosen to make it explicit that the use of resources on the toolkit (jobs, services, data, etc.) will be recorded by account.
Alice is about to kick off work on two separate projects, one is for a publication and another one is a proof-of-concept (POC) for a client. She opts to create two new accounts under her account sandbox_account.
eai account new acme.alice_sandbox.publication
eai account new acme.alice_sandbox.poc
Note that objects on the toolkit can be referenced by their 36-character UUID or by the name they have been assigned.
To reference an object by its name, one must list all of its parents all the way up to the root.
For instance, the reference for the admin role for the publication account below is acme.alice_sandbox.publication.admin
When an account is created, the two standard children roles are also created (admin and user) and the account creator is added as a member of the admin role. In our case, Alice is therefore added as an admin on both new accounts.
Alice can now start working with these accounts. She can:
Upload docker images to her accounts (
$ eai docker -h
)Upload data (
$ eai data -h
)Run jobs (
$ eai job -h
)and a lot more.
For most commands, she can specify under which account she
is launching the operation. If the flag is not specified, it will take her sandbox account as default
.
Note
Accounts can be subspaced. In the current scenario, acme.alice_sandbox
, acme.alice_sandbox.publication
acme.alice_sandbox.poc
are all valid accounts.
For the time being, we will assume Alice knows how to perform all these operations and will move on to how to set up an account that is to be shared with other users.
Step 3: Add another user as a collaborator user on an account
For this step, let’s assume that Bob has been added as a new user to the organization.
The organization now holds two users: Alice
and Bob
. Alice would really like some of Bob’s help with the experiments she is running for her paper publication.
She decides to give Bob access to the acme.alice_sandbox.publication account
. For that, she will need Bob’s user UUID (Bob can run $ eai user get
), or the name he has assigned to his
user object. (Bob can run $ eai user set --name bob
).
Alice can add Bob as member of the user role of her account with $ eai role member add acme.alice_sandbox.publication.user --user acme.bob
The organization now looks like this (note that some objects such as acme.user
and acme.admin
are no longer illustrated for simplicity purposes)
Bob can now perform a number of operations under the account acme.alice_sandbox.publication
(e.g, download docker images, download data, etc.). By default, the user role for a new account is given get
access to all resources.
The exact set of permissions assigned to Bob for that account is defined by policies associated with the user role.
Step 4: Creating a team
After a few days, Alice realizes that she will need more help than expected with the experimentations for her paper publication.
She decides to add one more user to the acme.alice_sandbox.publication account
.
# But this time, she decides to do this through a team, that she is naming avengers.
eai team new acme.avengers
# She adds herself, Bob and Charlie to the team:
eai team member add acme.avengers --user acme.alice --user acme.bob --user acme.charlie
# To check that everyone was added properly to the team, Alice can run:
eai team member ls acme.avengers
# She can then add the team as a member of the user role on the account
eai role member add acme.alice_sandbox.publication.user --team acme.avengers
While it is not depicted in the diagram above for simplicity, creating the team avenger also automatically created an account associated with the team (just like for when a new user is added to the organization). Therefore, the members of the team could, as an alternative, decide to collaborate by using the newly created account.
Step 5: Creating a guest role
Bob is also working on projects of his own. For one of these projects, that he has named account skunkworks, he wants to give other users visibility about what he is doing, but he definitely doesn’t want them to use the account to consume resources. He was granted a limited budget by his boss for this account and would hate for someone else to eat into this budget by running jobs…
First, Bob needs to add a new role to the skunkworks account and set get permissions for that guest role. Here, Bob is allowing guests to access information about jobs launched under the skunkworks account and about the data associated to that account as well. Note that set permissions are not provided, which means that guests won’t be able to launch jobs or overwrite any data under the skunkworks account.
ACCOUNT_URN=$(eai account get acme.skunkworks --field urn)
eai role new acme.skunkworks.guest --policy "*:get@${ACCOUNT_URN}:job:*+${ACCOUNT_URN}:data:*"
Note that we use a shell trick here to save the account URN in a variable to reuse it later.
Also, the +
and @
sign combination allows for multiple resources expressions (and/or multiple actions) by
applying a cartesian product between the list of actions (on the left of @
) and the list of resources (on the right). For example,
--policy a+b@c+d+e
is equivalent to --policy a@c --policy a@d --policy a@e --policy b@c
--policy b@d --policy b@e
.
Bob can now add members as guests to the account
eai role member add acme.skunkworks.guest --team acme.avengers
Tips
To manage policies tied to a role, run
eai role policy --help
for more details.To validate rules over resources, you can use
eai rule --help
. Consult the How To page to find example usages of that command.The
eai user policy ls
command only lists policies tied to your user account, not all policies tied to all your accounts.