Access control
Tarantool enables flexible management of access to various database resources. The main concepts of Tarantool access control system are as follows:
- A user is a person or program that interacts with a Tarantool instance.
- An object is an entity to which access can be granted, for example, a space, an index, or a function.
- A privilege allows a user to perform certain operations on specific objects, for example, creating spaces, reading or updating data.
- A role is a named collection of privileges that can be granted to a user.
A user identifies a person or program that interacts with a Tarantool instance. There might be different types of users, for example:
- A database administrator responsible for the overall management and administration of a database. An administrator can create other users and grant them specified privileges.
- A user with limited access to certain data and stored functions. Such users can get their privileges from the database administrator.
- Users used in communications between Tarantool instances. For example, such users can be created to maintain replication and sharding in a Tarantool cluster.
There are two built-in users in Tarantool:
-
adminis a user with all available administrative privileges. If the connection uses an admin-console port, the current user isadmin. For example,adminis used when connecting to an instance using tt connect locally using the instance name:$ tt connect app:instance001To allow remote binary port connections using the
adminuser, you need to set a password. -
guestis a user with minimum privileges used by default for remote binary port connections. For example,guestis used when connecting to an instance using tt connect using the IP address and port without specifying the name of a user:$ tt connect 192.168.10.10:3301
Any user (except guest) may have a password. If a password is not set,
a user cannot connect to Tarantool instances.
Tarantool password hashes are
stored in the _user system space. By default,
Tarantool uses the CHAP protocol to authenticate users and applies
SHA-1 hashing to passwords. So, if the
password is '123456', the stored hash is a string like
'a7SDfrdDKRBe5FaN2n3GftLKKtk='. In the Enterprise Edition, you can
enable PAP authentication with
the SHA256 hashing algorithm.
Tarantool Enterprise Edition allows you to improve database security by enforcing the use of strong passwords, setting up a maximum password age, and so on. Learn more from the configuration_authentication topic.
An object is a securable entity to which access can be granted. Tarantool has a number of objects that enable flexible management of access to data, stored functions, specific actions, and so on.
Below are a few examples of objects:
universerepresents a database (box.schema) that contains database objects, including spaces, indexes, users, roles, sequences, and functions. Granting privileges touniversegives a user access to any object in a database.spaceenables granting privileges to user-created or system spaces.functionenables granting privileges to functions.
The privileges granted to a user determine which operations the user can perform, for example:
- The
readandwritepermissions granted to thespaceobject allow a user to read or modify data in the specified space. - The
createpermission granted to thespaceobject allows a user to create new spaces. - The
executepermission granted to thefunctionobject allows a user to execute the specified function. - The
sessionpermission granted to theuniverseobject allows a user to connect to an instance over IPROTO. - The
usagepermission granted touniverseobject allows a user to use his privileges on database objects (for example, read, write, and alter space). - The
alterpermission granted to a user allows modifying its own settings, for example, a password. - The
droppermission granted to a user allows dropping users.
Note that some privileges might require read and write access to certain
system spaces. For example, the create permission granted to the
space object requires read and write permissions to the
_space system space. Similarly, granting the ability
to create functions requires read and write access to the
_func space.
A role is a container for privileges that can be granted to users. Roles can also be assigned to other roles, creating a role hierarchy.
There are the following built-in roles in Tarantool:
-
superhas all available administrative permissions. -
publichas certain read permissions. This role is automatically granted to new users when they are created. -
replicationcan be granted to a user used to maintain replication in a cluster. -
shardingcan be granted to a user used to maintain sharding in a cluster.
Below are a few diagrams that demonstrate how privileges can be granted to a user without and with using roles.
-
In this example, a user gets privileges directly without using roles.
user1 ── privilege1├─── privilege2└─── privilege3 -
In this example, a user gets all privileges provided by
role1and specific privileges assigned directly.user1 ── role1 ── privilege1│ └─── privilege2├─── privilege3└─── privilege4 -
In this example,
role2is granted torole1. This means that a user withrole1subsequently gets all privileges from both rolesrole1androle2.user1 ── role1 ── privilege1│ ├─── privilege2│ └─── role2│ ├─── privilege3│ └─── privilege4├─── privilege5└─── privilege6
An owner of a database object is the
user who created it. The owner of the database and the owner of objects
that are created initially (the system spaces and the default users) is
the admin user.
Owners automatically have privileges
for objects they create. They can
share these privileges with other
users or roles using box.schema.user.grant() and
box.schema.role.grant().
A session is the state of a connection to Tarantool. The session contains:
- An integer ID identifying the connection.
- The current user associated with the connection.
- The text description of the connected peer.
- A session's local state, such as Lua variables and functions.
In Tarantool, a single session can execute multiple concurrent transactions. Each transaction is identified by a unique integer ID, which can be queried at the start of the transaction using box.session.sync().
To create a new user, call box.schema.user.create(). In the example below, a user is created without a password:
box.schema.user.create('testuser')t.assert_equals(box.space._user.index.name:select { 'testuser' }[1][5]['chap-sha1'], nil)end)endg.test_user_with_password_created = function(cg)cg.server:exec(function()-- Create a user with a password --box.schema.user.create('testuser', { password = 'foobar' })-- End: Create a user with a password --t.assert_equals(box.space._user.index.name:select { 'testuser' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_current_user_password_set = function(cg)cg.server:exec(function()box.session.su('admin')-- Set a password for the current user --box.schema.user.passwd('foobar')-- End: Set a password for the current user --t.assert_equals(box.space._user.index.name:select { 'admin' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_specified_user_password_set = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Set a password for the specified user --box.schema.user.passwd('testuser', 'foobar')-- End: Set a password for the specified user --t.assert_equals(box.space._user.index.name:select { 'testuser' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_grant_revoke_privileges_user = function(cg)cg.server:exec(function()box.schema.user.create('testuser', { password = 'foobar' })box.schema.user.grant('testuser', 'execute', 'universe')-- Grant privileges to the specified user --box.schema.user.grant('testuser', 'read', 'space', 'writers')box.schema.user.grant('testuser', 'read,write', 'space', 'books')-- End: Grant privileges to the specified user --box.session.su('testuser')local _, delete_writer_error = pcall(function()box.space.writers:delete(3)end)t.assert_equals(delete_writer_error:unpack().message, "Write access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Revoke space reading --box.schema.user.revoke('testuser', 'write', 'space', 'books')-- End: Revoke space reading --box.session.su('testuser')local _, delete_book_error = pcall(function()box.space.books:delete(10)end)t.assert_equals(delete_book_error:unpack().message, "Write access to space 'books' is denied for user 'testuser'")box.session.su('admin')-- Revoke session --box.schema.user.revoke('testuser', 'session', 'universe')-- End: Revoke session --local _, change_user_error = pcall(function()box.session.su('testuser')end)t.assert_equals(change_user_error:unpack().message, "Session access to universe '' is denied for user 'testuser'")end)endg.test_user_dropped = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Drop a user --box.schema.user.drop('testuser')-- End: Drop a user --t.assert_equals(box.schema.user.exists('testuser'), false)end)end
In this example, the password is specified in the options parameter:
box.schema.user.create('testuser', { password = 'foobar' })t.assert_equals(box.space._user.index.name:select { 'testuser' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_current_user_password_set = function(cg)cg.server:exec(function()box.session.su('admin')-- Set a password for the current user --box.schema.user.passwd('foobar')-- End: Set a password for the current user --t.assert_equals(box.space._user.index.name:select { 'admin' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_specified_user_password_set = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Set a password for the specified user --box.schema.user.passwd('testuser', 'foobar')-- End: Set a password for the specified user --t.assert_equals(box.space._user.index.name:select { 'testuser' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_grant_revoke_privileges_user = function(cg)cg.server:exec(function()box.schema.user.create('testuser', { password = 'foobar' })box.schema.user.grant('testuser', 'execute', 'universe')-- Grant privileges to the specified user --box.schema.user.grant('testuser', 'read', 'space', 'writers')box.schema.user.grant('testuser', 'read,write', 'space', 'books')-- End: Grant privileges to the specified user --box.session.su('testuser')local _, delete_writer_error = pcall(function()box.space.writers:delete(3)end)t.assert_equals(delete_writer_error:unpack().message, "Write access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Revoke space reading --box.schema.user.revoke('testuser', 'write', 'space', 'books')-- End: Revoke space reading --box.session.su('testuser')local _, delete_book_error = pcall(function()box.space.books:delete(10)end)t.assert_equals(delete_book_error:unpack().message, "Write access to space 'books' is denied for user 'testuser'")box.session.su('admin')-- Revoke session --box.schema.user.revoke('testuser', 'session', 'universe')-- End: Revoke session --local _, change_user_error = pcall(function()box.session.su('testuser')end)t.assert_equals(change_user_error:unpack().message, "Session access to universe '' is denied for user 'testuser'")end)endg.test_user_dropped = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Drop a user --box.schema.user.drop('testuser')-- End: Drop a user --t.assert_equals(box.schema.user.exists('testuser'), false)end)end
To set or change a user's password, use box.schema.user.passwd(). In the example below, a user password is set for a currently logged-in user:
box.schema.user.passwd('foobar')t.assert_equals(box.space._user.index.name:select { 'admin' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_specified_user_password_set = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Set a password for the specified user --box.schema.user.passwd('testuser', 'foobar')-- End: Set a password for the specified user --t.assert_equals(box.space._user.index.name:select { 'testuser' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_grant_revoke_privileges_user = function(cg)cg.server:exec(function()box.schema.user.create('testuser', { password = 'foobar' })box.schema.user.grant('testuser', 'execute', 'universe')-- Grant privileges to the specified user --box.schema.user.grant('testuser', 'read', 'space', 'writers')box.schema.user.grant('testuser', 'read,write', 'space', 'books')-- End: Grant privileges to the specified user --box.session.su('testuser')local _, delete_writer_error = pcall(function()box.space.writers:delete(3)end)t.assert_equals(delete_writer_error:unpack().message, "Write access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Revoke space reading --box.schema.user.revoke('testuser', 'write', 'space', 'books')-- End: Revoke space reading --box.session.su('testuser')local _, delete_book_error = pcall(function()box.space.books:delete(10)end)t.assert_equals(delete_book_error:unpack().message, "Write access to space 'books' is denied for user 'testuser'")box.session.su('admin')-- Revoke session --box.schema.user.revoke('testuser', 'session', 'universe')-- End: Revoke session --local _, change_user_error = pcall(function()box.session.su('testuser')end)t.assert_equals(change_user_error:unpack().message, "Session access to universe '' is denied for user 'testuser'")end)endg.test_user_dropped = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Drop a user --box.schema.user.drop('testuser')-- End: Drop a user --t.assert_equals(box.schema.user.exists('testuser'), false)end)end
To set the password for the specified user, pass a username and password as shown below:
box.schema.user.passwd('testuser', 'foobar')t.assert_equals(box.space._user.index.name:select { 'testuser' }[1][5]['chap-sha1'], 'm1ADQ7xS4pERcutSrlz0hHYExuU=')end)endg.test_grant_revoke_privileges_user = function(cg)cg.server:exec(function()box.schema.user.create('testuser', { password = 'foobar' })box.schema.user.grant('testuser', 'execute', 'universe')-- Grant privileges to the specified user --box.schema.user.grant('testuser', 'read', 'space', 'writers')box.schema.user.grant('testuser', 'read,write', 'space', 'books')-- End: Grant privileges to the specified user --box.session.su('testuser')local _, delete_writer_error = pcall(function()box.space.writers:delete(3)end)t.assert_equals(delete_writer_error:unpack().message, "Write access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Revoke space reading --box.schema.user.revoke('testuser', 'write', 'space', 'books')-- End: Revoke space reading --box.session.su('testuser')local _, delete_book_error = pcall(function()box.space.books:delete(10)end)t.assert_equals(delete_book_error:unpack().message, "Write access to space 'books' is denied for user 'testuser'")box.session.su('admin')-- Revoke session --box.schema.user.revoke('testuser', 'session', 'universe')-- End: Revoke session --local _, change_user_error = pcall(function()box.session.su('testuser')end)t.assert_equals(change_user_error:unpack().message, "Session access to universe '' is denied for user 'testuser'")end)endg.test_user_dropped = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Drop a user --box.schema.user.drop('testuser')-- End: Drop a user --t.assert_equals(box.schema.user.exists('testuser'), false)end)end
To grant the specified privileges to a user, use the
box.schema.user.grant() function. In the
example below, testuser gets read permissions to the writers space
and read/write permissions to the books space:
box.schema.user.grant('testuser', 'read', 'space', 'writers')box.schema.user.grant('testuser', 'read,write', 'space', 'books')box.session.su('testuser')local _, delete_writer_error = pcall(function()box.space.writers:delete(3)end)t.assert_equals(delete_writer_error:unpack().message, "Write access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Revoke space reading --box.schema.user.revoke('testuser', 'write', 'space', 'books')-- End: Revoke space reading --box.session.su('testuser')local _, delete_book_error = pcall(function()box.space.books:delete(10)end)t.assert_equals(delete_book_error:unpack().message, "Write access to space 'books' is denied for user 'testuser'")box.session.su('admin')-- Revoke session --box.schema.user.revoke('testuser', 'session', 'universe')-- End: Revoke session --local _, change_user_error = pcall(function()box.session.su('testuser')end)t.assert_equals(change_user_error:unpack().message, "Session access to universe '' is denied for user 'testuser'")end)endg.test_user_dropped = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Drop a user --box.schema.user.drop('testuser')-- End: Drop a user --t.assert_equals(box.schema.user.exists('testuser'), false)end)end
Learn more about granting privileges to different types of objects from access_control_granting_privileges.
To check whether the specified user exists, call box.schema.user.exists():
box.schema.user.exists('testuser')--[[- true--]]
To get information about privileges granted to a user, call box.schema.user.info():
box.schema.user.info('testuser')--[[- - - execute- role- public- - read- space- writers- - read,write- space- books- - session,usage- universe-- - alter- user- testuser--]]
In the example above, testuser has the following privileges:
- The
executepermission to thepublicrole means that this role is assigned to the user. - The
readpermission to thewritersspace means that the user can read data from this space. - The
read,writepermissions to thebooksspace mean that the user can read and modify data in this space. - The
session,usagepermissions touniversemean the following:session: the user can authenticate over an IPROTO connection.usage: lets the user use their privileges on database objects (for example, read and modify data in a space).
- The
alterpermission letstestusermodify its own settings, for example, a password.
To revoke the specified privileges, use the
box.schema.user.revoke() function. In the
example below, write access to the books space is revoked:
box.schema.user.revoke('testuser', 'write', 'space', 'books')box.session.su('testuser')local _, delete_book_error = pcall(function()box.space.books:delete(10)end)t.assert_equals(delete_book_error:unpack().message, "Write access to space 'books' is denied for user 'testuser'")box.session.su('admin')-- Revoke session --box.schema.user.revoke('testuser', 'session', 'universe')-- End: Revoke session --local _, change_user_error = pcall(function()box.session.su('testuser')end)t.assert_equals(change_user_error:unpack().message, "Session access to universe '' is denied for user 'testuser'")end)endg.test_user_dropped = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Drop a user --box.schema.user.drop('testuser')-- End: Drop a user --t.assert_equals(box.schema.user.exists('testuser'), false)end)end
Revoking the session permission to universe can be used to disallow
a user to connect to a Tarantool instance:
box.schema.user.revoke('testuser', 'session', 'universe')local _, change_user_error = pcall(function()box.session.su('testuser')end)t.assert_equals(change_user_error:unpack().message, "Session access to universe '' is denied for user 'testuser'")end)endg.test_user_dropped = function(cg)cg.server:exec(function()box.schema.user.create('testuser')-- Drop a user --box.schema.user.drop('testuser')-- End: Drop a user --t.assert_equals(box.schema.user.exists('testuser'), false)end)end
The current user name can be found using box.session.user().
box.session.user()--[[- admin--]]
The current user can be changed:
-
For an admin-console connection: using box.session.su():
box.session.su('testuser')box.session.user()--[[- testuser--]] -
For a binary port connection: using the AUTH protocol command, supported by most clients.
-
For a binary-port connection invoking a stored function with the CALL command: if the SETUID property is enabled for the function, Tarantool temporarily replaces the current user with the function's creator, with all the creator's privileges, during function execution.
To drop the specified user, call box.schema.user.drop():
box.schema.user.drop('testuser')t.assert_equals(box.schema.user.exists('testuser'), false)end)end
To create a new role, call box.schema.role.create(). In the example below, two roles are created:
box.schema.role.create('books_space_manager')box.schema.role.create('writers_space_reader')-- Grant read/write privileges to a role --box.schema.role.grant('books_space_manager', 'read,write', 'space', 'books')-- Grant write privileges to a role --box.schema.role.grant('writers_space_reader', 'read', 'space', 'writers')-- End: Grant privileges to roles ---- Grant a role to a role --box.schema.role.create('all_spaces_manager')box.schema.role.grant('all_spaces_manager', 'books_space_manager')box.schema.role.grant('all_spaces_manager', 'writers_space_reader')-- End: Grant a role to a role ---- Grant a role to a user --box.schema.user.grant('testuser', 'books_space_manager')box.schema.user.grant('testuser', 'writers_space_reader')-- End: Grant a role to a user ---- Test removing a tuple from 'writers' --box.session.su('testuser')local _, delete_writer_error = pcall(function()box.space.writers:delete(3)end)t.assert_equals(delete_writer_error:unpack().message, "Write access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Revoking a role from a user --box.schema.user.revoke('testuser', 'execute', 'role', 'writers_space_reader')-- End: Revoking a role from a user ---- Test selecting data from 'writers' --box.session.su('testuser')local _, select_writer_error = pcall(function()box.space.writers:select(3)end)t.assert_equals(select_writer_error:unpack().message, "Read access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Dropping a role --box.schema.role.drop('writers_space_reader')-- End: Dropping a role ---- Test roles exist --t.assert_equals(box.schema.role.exists('books_space_manager'), true)t.assert_equals(box.schema.role.exists('all_spaces_manager'), true)t.assert_equals(box.schema.role.exists('writers_space_reader'), false)end)end
To grant the specified privileges to a role, use the
box.schema.role.grant() function. In the
example below, the books_space_manager role gets read and write
permissions to the books space:
box.schema.role.grant('books_space_manager', 'read,write', 'space', 'books')
The writers_space_reader role gets read permissions to the writers
space:
box.schema.role.grant('writers_space_reader', 'read', 'space', 'writers')
Learn more about granting privileges to different types of objects from access_control_granting_privileges.
Roles can be assigned to other roles. In the example below, the newly
created all_spaces_manager role gets all privileges granted to
books_space_manager and writers_space_reader:
box.schema.role.create('all_spaces_manager')box.schema.role.grant('all_spaces_manager', 'books_space_manager')box.schema.role.grant('all_spaces_manager', 'writers_space_reader')-- Grant a role to a user --box.schema.user.grant('testuser', 'books_space_manager')box.schema.user.grant('testuser', 'writers_space_reader')-- End: Grant a role to a user ---- Test removing a tuple from 'writers' --box.session.su('testuser')local _, delete_writer_error = pcall(function()box.space.writers:delete(3)end)t.assert_equals(delete_writer_error:unpack().message, "Write access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Revoking a role from a user --box.schema.user.revoke('testuser', 'execute', 'role', 'writers_space_reader')-- End: Revoking a role from a user ---- Test selecting data from 'writers' --box.session.su('testuser')local _, select_writer_error = pcall(function()box.space.writers:select(3)end)t.assert_equals(select_writer_error:unpack().message, "Read access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Dropping a role --box.schema.role.drop('writers_space_reader')-- End: Dropping a role ---- Test roles exist --t.assert_equals(box.schema.role.exists('books_space_manager'), true)t.assert_equals(box.schema.role.exists('all_spaces_manager'), true)t.assert_equals(box.schema.role.exists('writers_space_reader'), false)end)end
To grant the specified role to a user, use the
box.schema.user.grant() function. In the example below, testuser
gets privileges granted to the books_space_manager and
writers_space_reader roles:
box.schema.user.grant('testuser', 'books_space_manager')box.schema.user.grant('testuser', 'writers_space_reader')-- Test removing a tuple from 'writers' --box.session.su('testuser')local _, delete_writer_error = pcall(function()box.space.writers:delete(3)end)t.assert_equals(delete_writer_error:unpack().message, "Write access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Revoking a role from a user --box.schema.user.revoke('testuser', 'execute', 'role', 'writers_space_reader')-- End: Revoking a role from a user ---- Test selecting data from 'writers' --box.session.su('testuser')local _, select_writer_error = pcall(function()box.space.writers:select(3)end)t.assert_equals(select_writer_error:unpack().message, "Read access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Dropping a role --box.schema.role.drop('writers_space_reader')-- End: Dropping a role ---- Test roles exist --t.assert_equals(box.schema.role.exists('books_space_manager'), true)t.assert_equals(box.schema.role.exists('all_spaces_manager'), true)t.assert_equals(box.schema.role.exists('writers_space_reader'), false)end)end
To check whether the specified role exists, call box.schema.role.exists():
box.schema.role.exists('books_space_manager')--[[- true--]]
To get information about privileges granted to a role, call box.schema.role.info():
box.schema.role.info('books_space_manager')--[[- - - read,write- space- books--]]
If a role has the execute permission to other roles, this means that
these roles are
granted to this parent role:
box.schema.role.info('all_spaces_manager')--[[- - - execute- role- books_space_manager- - execute- role- writers_space_reader--]]
To revoke the specified role from a user, revoke the execute privilege
for this role using the
box.schema.user.revoke() function. In the
example below, the books_space_reader role is revoked from testuser:
box.schema.user.revoke('testuser', 'execute', 'role', 'writers_space_reader')-- Test selecting data from 'writers' --box.session.su('testuser')local _, select_writer_error = pcall(function()box.space.writers:select(3)end)t.assert_equals(select_writer_error:unpack().message, "Read access to space 'writers' is denied for user 'testuser'")box.session.su('admin')-- Dropping a role --box.schema.role.drop('writers_space_reader')-- End: Dropping a role ---- Test roles exist --t.assert_equals(box.schema.role.exists('books_space_manager'), true)t.assert_equals(box.schema.role.exists('all_spaces_manager'), true)t.assert_equals(box.schema.role.exists('writers_space_reader'), false)end)end
To revoke role's privileges, use box.schema.role.revoke().
To drop the specified role, call box.schema.role.drop():
box.schema.role.drop('writers_space_reader')-- Test roles exist --t.assert_equals(box.schema.role.exists('books_space_manager'), true)t.assert_equals(box.schema.role.exists('all_spaces_manager'), true)t.assert_equals(box.schema.role.exists('writers_space_reader'), false)end)end
To grant the specified privileges to a user or role, use the
box.schema.user.grant() and
box.schema.role.grant() functions, which have
similar signatures and accept the same set of arguments. For example,
the box.schema.user.grant() signature looks as follows:
box.schema.user.grant(username, permissions, object-type, object-name[, {options}])
-
username: the name of the user that gets the specified privileges. -
permissions: a string value that represents permissions granted to the user. If there are several permissions, they should be separated by commas without a space. -
object-type: a type of object to which permissions are granted. -
object-name: the name of the object to which permissions are granted. An empty string ("") ornilprovided instead ofobject-namegrants the specified permissions to all objects of the specified type.
In the example below, testuser gets privileges allowing them to create
any object of any type:
box.schema.user.grant('testuser','read,write,create','universe')
In this example, testuser can grant access to objects that testuser
created:
box.schema.user.grant('testuser','write','space','_priv')
In the example below, testuser gets privileges allowing them to create
spaces:
box.schema.user.grant('testuser','create','space')box.schema.user.grant('testuser','write', 'space', '_schema')box.schema.user.grant('testuser','write', 'space', '_space')
As you can see, the ability to create spaces also requires write
access to certain system spaces.
To allow testuser to drop a space that has associated objects, add the
following privileges:
box.schema.user.grant('testuser','create,drop','space')box.schema.user.grant('testuser','write','space','_schema')box.schema.user.grant('testuser','write','space','_space')box.schema.user.grant('testuser','write','space','_space_sequence')box.schema.user.grant('testuser','read','space','_trigger')box.schema.user.grant('testuser','read','space','_fk_constraint')box.schema.user.grant('testuser','read','space','_ck_constraint')box.schema.user.grant('testuser','read','space','_func_index')
In the example below, testuser gets privileges allowing them to create
indexes in the 'writers' space:
box.schema.user.grant('testuser','create,read','space','writers')box.schema.user.grant('testuser','read,write','space','_space_sequence')box.schema.user.grant('testuser','write', 'space', '_index')
To allow testuser to alter indexes in the writers space, grant the
privileges below. This example assumes that indexes in the writers
space are not created by testuser.
box.schema.user.grant('testuser','alter','space','writers')box.schema.user.grant('testuser','read','space','_space')box.schema.user.grant('testuser','read','space','_index')box.schema.user.grant('testuser','read','space','_space_sequence')box.schema.user.grant('testuser','write','space','_index')
If testuser created indexes in the writers space, granting the
following privileges is enough to alter indexes:
box.schema.user.grant('testuser','read','space','_space_sequence')box.schema.user.grant('testuser','read,write','space','_index')
In this example, testuser gets privileges allowing them to
select data from the 'writers' space:
box.schema.user.grant('testuser','read','space','writers')
In this example, testuser is allowed to read and modify data in the
'books' space:
box.schema.user.grant('testuser','read,write','space','books')
In this example, testuser gets privileges to create
sequence generators:
box.schema.user.grant('testuser','create','sequence')box.schema.user.grant('testuser', 'read,write', 'space', '_sequence')
To let testuser drop a sequence, grant them the following privileges:
box.schema.user.grant('testuser','drop','sequence')box.schema.user.grant('testuser','write','space','_sequence_data')box.schema.user.grant('testuser','write','space','_sequence')
In this example, testuser is allowed to use the id_seq:next()
function with a sequence named 'id_seq':
box.schema.user.grant('testuser','read,write','sequence','id_seq')
In the next example, testuser is allowed to use the id_seq:set() or
id_seq:reset() functions with a sequence named 'id_seq':
box.schema.user.grant('testuser','write','sequence','id_seq')
In this example, testuser gets privileges to create
functions:
box.schema.user.grant('testuser','create','function')box.schema.user.grant('testuser','read,write','space','_func')
To let testuser drop a function, grant them the following privileges:
box.schema.user.grant('testuser','drop','function')box.schema.user.grant('testuser','write','space','_func')
To give the ability to execute a function named 'sum', grant the following privileges:
box.schema.user.grant('testuser','execute','function','sum')
Granting the 'execute' privilege on lua_call permits the user to
call any global (accessible via the _G Lua table) user-defined Lua
function with the IPROTO_CALL request. To grant permission to any
non-persistent function, you need to specify its name when granting the
lua_call privilege.
function my_func_1() endfunction my_func_2() endbox.cfg({listen = 3301})box.schema.user.create('alice', {password = 'secret'})conn = require('net.box').connect(box.cfg.listen, {user = 'alice', password = 'secret'})box.schema.user.grant('alice', 'execute', 'lua_call', 'my_func_1')conn:call('my_func_1') -- okconn:call('my_func_2') -- access deniedbox.schema.user.grant('alice', 'execute', 'lua_call', 'box.session.su')conn:call('box.session.su', {'admin'}) -- ok
In this example, testuser gets privileges to create other users:
box.schema.user.grant('testuser','create','user')box.schema.user.grant('testuser', 'read,write', 'space', '_user')box.schema.user.grant('testuser', 'write', 'space', '_priv')
To let testuser create new roles, grant the following privileges:
box.schema.user.grant('testuser','create','role')box.schema.user.grant('testuser', 'read,write', 'space', '_user')box.schema.user.grant('testuser', 'write', 'space', '_priv')
To let testuser execute Lua code, grant the execute privilege to the
lua_eval object:
box.schema.user.grant('testuser','execute','lua_eval')
Similarly, executing an arbitrary SQL expression requires the execute
privilege to the sql object:
box.schema.user.grant('testuser','execute','sql')
In the example below, the created Lua function is executed on behalf of its creator, even if called by another user.
First, the two spaces (space1 and space2) are created, and a
no-password user (private_user) is granted full access to them. Then
read_and_modify is defined and private_user becomes this function's
creator. Finally, another user (public_user) is granted access to
execute Lua functions created by private_user.
box.schema.space.create('space1')box.schema.space.create('space2')box.space.space1:create_index('pk')box.space.space2:create_index('pk')box.schema.user.create('private_user')box.schema.user.grant('private_user', 'read,write', 'space', 'space1')box.schema.user.grant('private_user', 'read,write', 'space', 'space2')box.schema.user.grant('private_user', 'create', 'universe')box.schema.user.grant('private_user', 'read,write', 'space', '_func')function read_and_modify(key)local space1 = box.space.space1local space2 = box.space.space2local fiber = require('fiber')local t = space1:get{key}if t ~= nil thenspace1:put{key, box.session.uid()}space2:put{key, fiber.time()}endendbox.session.su('private_user')box.schema.func.create('read_and_modify', {setuid= true})box.session.su('admin')box.schema.user.create('public_user', {password = 'secret'})box.schema.user.grant('public_user', 'execute', 'function', 'read_and_modify')
Whenever public_user calls the function, it is executed on behalf of
its creator, private_user.
Object type | Description |
|---|---|
| A database (box.schema) that contains database objects, including spaces, indexes, users, roles, sequences, and functions. Granting privileges to |
| A user. |
| A role. |
| A space. |
| A function. |
| A sequence. |
| Executing arbitrary Lua code. |
| Calling any global user-defined Lua function. |
| Executing an arbitrary SQL expression. |
Permission | Object type | Granted to roles | Description |
|---|---|---|---|
| All | Yes | Allows reading data of the specified object. For example, this permission can be used to allow a user to select data from the specified space. |
| All | Yes | Allows updating data of the specified object. For example, this permission can be used to allow a user to modify data in the specified space. |
| All | Yes | Allows creating objects of the specified type. For example, this permission can be used to allow a user to create new spaces. Note that this permission requires read and write access to certain system spaces. |
| All | Yes | Allows altering objects of the specified type. Note that this permission requires read and write access to certain system spaces. |
| All | Yes | Allows dropping objects of the specified type. Note that this permission requires read and write access to certain system spaces. |
|
| Yes | For |
|
| No | Allows a user to connect to an instance over IPROTO. |
|
| No | Allows a user to use their privileges on database objects (for example, read, write, and alter spaces). |
Object type | Details |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|