-
Notifications
You must be signed in to change notification settings - Fork 43
Rework the Access control topic #4024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
642f95b
3b36fa7
5f25f00
4e3b3da
c99cdfa
04077b7
99248cd
0f48f28
49f53c7
f28b61b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
local fio = require('fio') | ||
local server = require('luatest.server') | ||
local t = require('luatest') | ||
local g = t.group() | ||
g.before_all(function(cg) | ||
cg.server = server:new { | ||
box_cfg = {}, | ||
workdir = fio.cwd() .. '/tmp' | ||
} | ||
cg.server:start() | ||
cg.server:exec(function() | ||
box.schema.space.create('writers') | ||
box.space.writers:format({ | ||
{ name = 'id', type = 'unsigned' }, | ||
{ name = 'name', type = 'string' } | ||
}) | ||
box.space.writers:create_index('primary', { parts = { 'id' } }) | ||
|
||
box.schema.space.create('books') | ||
box.space.books:format({ | ||
{ name = 'id', type = 'unsigned' }, | ||
{ name = 'title', type = 'string' }, | ||
{ name = 'author_id', foreign_key = { space = 'writers', field = 'id' } }, | ||
}) | ||
box.space.books:create_index('primary', { parts = { 'id' } }) | ||
|
||
box.space.writers:insert { 1, 'Leo Tolstoy' } | ||
box.space.writers:insert { 2, 'Fyodor Dostoevsky' } | ||
box.space.writers:insert { 3, 'Alexander Pushkin' } | ||
|
||
box.space.books:insert { 1, 'War and Peace', 1 } | ||
box.space.books:insert { 2, 'Anna Karenina', 1 } | ||
box.space.books:insert { 3, 'Resurrection', 1 } | ||
box.space.books:insert { 4, 'Crime and Punishment', 2 } | ||
box.space.books:insert { 5, 'The Idiot', 2 } | ||
box.space.books:insert { 6, 'The Brothers Karamazov', 2 } | ||
box.space.books:insert { 7, 'Eugene Onegin', 3 } | ||
box.space.books:insert { 8, 'The Captain\'s Daughter', 3 } | ||
box.space.books:insert { 9, 'Boris Godunov', 3 } | ||
box.space.books:insert { 10, 'Ruslan and Ludmila', 3 } | ||
end) | ||
end) | ||
|
||
g.after_all(function(cg) | ||
cg.server:drop() | ||
fio.rmtree(cg.server.workdir) | ||
end) | ||
|
||
g.test_role_granted_revoked = function(cg) | ||
cg.server:exec(function() | ||
box.schema.user.create('testuser', { password = 'foobar' }) | ||
|
||
-- Create roles -- | ||
box.schema.role.create('books_space_manager') | ||
box.schema.role.create('writers_space_reader') | ||
-- End: Create roles -- | ||
|
||
-- 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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
local fio = require('fio') | ||
local server = require('luatest.server') | ||
local t = require('luatest') | ||
local g = t.group() | ||
g.before_all(function(cg) | ||
cg.server = server:new { | ||
box_cfg = {}, | ||
workdir = fio.cwd() .. '/tmp' | ||
} | ||
cg.server:start() | ||
cg.server:exec(function() | ||
box.schema.space.create('writers') | ||
box.space.writers:format({ | ||
{ name = 'id', type = 'unsigned' }, | ||
{ name = 'name', type = 'string' } | ||
}) | ||
box.space.writers:create_index('primary', { parts = { 'id' } }) | ||
|
||
box.schema.space.create('books') | ||
box.space.books:format({ | ||
{ name = 'id', type = 'unsigned' }, | ||
{ name = 'title', type = 'string' }, | ||
{ name = 'author_id', foreign_key = { space = 'writers', field = 'id' } }, | ||
}) | ||
box.space.books:create_index('primary', { parts = { 'id' } }) | ||
|
||
box.space.writers:insert { 1, 'Leo Tolstoy' } | ||
box.space.writers:insert { 2, 'Fyodor Dostoevsky' } | ||
box.space.writers:insert { 3, 'Alexander Pushkin' } | ||
|
||
box.space.books:insert { 1, 'War and Peace', 1 } | ||
box.space.books:insert { 2, 'Anna Karenina', 1 } | ||
box.space.books:insert { 3, 'Resurrection', 1 } | ||
box.space.books:insert { 4, 'Crime and Punishment', 2 } | ||
box.space.books:insert { 5, 'The Idiot', 2 } | ||
box.space.books:insert { 6, 'The Brothers Karamazov', 2 } | ||
box.space.books:insert { 7, 'Eugene Onegin', 3 } | ||
box.space.books:insert { 8, 'The Captain\'s Daughter', 3 } | ||
box.space.books:insert { 9, 'Boris Godunov', 3 } | ||
box.space.books:insert { 10, 'Ruslan and Ludmila', 3 } | ||
end) | ||
end) | ||
|
||
g.after_each(function(cg) | ||
cg.server:exec(function() | ||
if box.schema.user.exists('testuser') then | ||
box.schema.user.drop('testuser') | ||
end | ||
end) | ||
end) | ||
|
||
g.after_all(function(cg) | ||
cg.server:drop() | ||
fio.rmtree(cg.server.workdir) | ||
end) | ||
|
||
g.test_user_without_password_created = function(cg) | ||
cg.server:exec(function() | ||
-- Create a user without a password -- | ||
box.schema.user.create('testuser') | ||
-- End: Create a user without a password -- | ||
t.assert_equals(box.space._user.index.name:select { 'testuser' }[1][5]['chap-sha1'], nil) | ||
end) | ||
end | ||
|
||
g.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) | ||
end | ||
|
||
g.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) | ||
end | ||
|
||
g.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) | ||
end | ||
|
||
g.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) | ||
end | ||
|
||
g.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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,7 @@ box.schema.user.create() | |
* ``password`` (default = '') - string; the ``password`` = *password* | ||
specification is good because in a :ref:`URI <index-uri>` | ||
(Uniform Resource Identifier) it is usually illegal to include a | ||
user-name without a password. | ||
username without a password. | ||
|
||
.. NOTE:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also described in Limitations: https://www.tarantool.io/en/doc/latest/book/box/limitations/. |
||
|
||
|
@@ -34,8 +34,10 @@ box.schema.user.create() | |
|
||
**Examples:** | ||
|
||
.. code-block:: lua | ||
.. literalinclude:: /code_snippets/test/access_control/grant_user_privileges_test.lua | ||
:language: lua | ||
:start-after: Create a user with a password | ||
:end-before: End: Create a user with a password | ||
:dedent: | ||
|
||
box.schema.user.create('testuser') | ||
box.schema.user.create('testuser', {password = 'foobar'}) | ||
box.schema.user.create('testuser', {if_not_exists = false}) | ||
See also: :ref:`access_control_users`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: most style guides recommend avoiding
foo
/bar
anywhere in examples.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually password is "secret", or something similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your suggestion. Honestly, I try not to use meaningful words as password examples in docs because they make a reader think about the word meaning. IMO, passwords should look like some gibberish, well-known weak passwords (
123456
), or smth likeP@$$word
) to allow a reader quickly scan it und understand it is a password, not smth else. Not sure I'm right here :)