mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
select.py: requirements cleanup + syntax update
This commit is contained in:
commit
4910435f6c
@ -1,6 +1,6 @@
|
||||
<yandex>
|
||||
<timezone>Europe/Moscow</timezone>
|
||||
<listen_host replace="replace">0.0.0.0</listen_host>
|
||||
<listen_host replace="replace">::</listen_host>
|
||||
<path>/var/lib/clickhouse/</path>
|
||||
<tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
|
||||
</yandex>
|
||||
|
@ -8,7 +8,37 @@ from helpers.cluster import Cluster
|
||||
from helpers.argparser import argparser
|
||||
from rbac.requirements import *
|
||||
|
||||
issue_12507 = "https://github.com/ClickHouse/ClickHouse/issues/12507"
|
||||
issue_12510 = "https://github.com/ClickHouse/ClickHouse/issues/12510"
|
||||
issue_12600 = "https://github.com/ClickHouse/ClickHouse/issues/12600"
|
||||
|
||||
xfails = {
|
||||
"syntax/show create quota/I show create quota current":
|
||||
[(Fail, "https://github.com/ClickHouse/ClickHouse/issues/12495")],
|
||||
"syntax/create role/I create role that already exists, throws exception":
|
||||
[(Fail, issue_12510)],
|
||||
"syntax/create user/I create user with if not exists, user does exist":
|
||||
[(Fail, issue_12507)],
|
||||
"syntax/create row policy/I create row policy if not exists, policy does exist":
|
||||
[(Fail, issue_12507)],
|
||||
"syntax/create quota/I create quota if not exists, quota does exist":
|
||||
[(Fail, issue_12507)],
|
||||
"syntax/create role/I create role if not exists, role does exist":
|
||||
[(Fail, issue_12507)],
|
||||
"syntax/create settings profile/I create settings profile if not exists, profile does exist":
|
||||
[(Fail, issue_12507)],
|
||||
"syntax/grant privilege/grant privileges/privilege='dictGet', on=('db0.table0', 'db0.*', '*.*', 'tb0', '*'), allow_introspection=False":
|
||||
[(Fail, issue_12600)],
|
||||
"syntax/grant privilege/grant privileges/privilege='CREATE', on=('db0.table0', 'db0.*', '*.*', 'tb0', '*'), allow_introspection=False":
|
||||
[(Fail, issue_12600)],
|
||||
"syntax/grant privilege/grant privileges/privilege='DROP', on=('db0.table0', 'db0.*', '*.*', 'tb0', '*'), allow_introspection=False":
|
||||
[(Fail, issue_12600)],
|
||||
"syntax/grant privilege/grant privileges/privilege='TRUNCATE', on=('db0.table0', 'db0.*', '*.*', 'tb0', '*'), allow_introspection=False":
|
||||
[(Fail, issue_12600)],
|
||||
"syntax/grant privilege/grant privileges/privilege='OPTIMIZE', on=('db0.table0', 'db0.*', '*.*', 'tb0', '*'), allow_introspection=False":
|
||||
[(Fail, issue_12600)],
|
||||
"syntax/grant privilege/grant privileges/privilege='SYSTEM', on=('db0.table0', 'db0.*', '*.*', 'tb0', '*'), allow_introspection=False":
|
||||
[(Fail, issue_12600)],
|
||||
}
|
||||
|
||||
@TestModule
|
||||
@ -25,6 +55,7 @@ def regression(self, local, clickhouse_binary_path):
|
||||
with Cluster(local, clickhouse_binary_path, nodes=nodes) as cluster:
|
||||
self.context.cluster = cluster
|
||||
|
||||
Feature(run=load("rbac.tests.syntax.feature", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.privileges.feature", "feature"), flags=TE)
|
||||
|
||||
if main():
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
# These requirements were auto generated
|
||||
# from software requirements specification (SRS)
|
||||
# document by TestFlows v1.6.200723.1011705.
|
||||
# document by TestFlows v1.6.200731.1222107.
|
||||
# Do not edit by hand but re-generate instead
|
||||
# using 'tfs requirements generate' command.
|
||||
from testflows.core import Requirement
|
||||
@ -316,329 +316,6 @@ RQ_SRS_006_RBAC_Role_RowPolicies = Requirement(
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Usage = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Usage',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **usage** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **select** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_SelectColumns = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.SelectColumns',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **select columns** privilege\n'
|
||||
'for a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **insert** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Delete = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Delete',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **delete** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Alter = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Alter',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **alter** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Create = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Create',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **create** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Drop = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Drop',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **drop** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_All = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.All',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL include in the **all** privilege the same rights\n'
|
||||
'as provided by **usage**, **select**, **select columns**,\n'
|
||||
'**insert**, **delete**, **alter**, **create**, and **drop** privileges.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_All_GrantRevoke = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.All.GrantRevoke',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **all** privileges\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_GrantOption = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.GrantOption',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **grant option** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_AdminOption = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.AdminOption',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **admin option** privilege\n'
|
||||
'to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Insert = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Insert',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `INSERT INTO` statements\n'
|
||||
'to be executed unless the user has the **insert** privilege for the destination table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Select',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `SELECT` statements\n'
|
||||
'to be executed unless the user has the **select** or **select columns** privilege\n'
|
||||
'for the destination table either because of the explicit grant\n'
|
||||
'or through one of the roles assigned to the user.\n'
|
||||
'If the the user only has the **select columns**\n'
|
||||
'privilege then only the specified columns SHALL be available for reading.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Create = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Create',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `CREATE` statements\n'
|
||||
'to be executed unless the user has the **create** privilege for the destination database\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Alter = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Alter',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `ALTER` statements\n'
|
||||
'to be executed unless the user has the **alter** privilege for the destination table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Drop = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Drop',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `DROP` statements\n'
|
||||
'to be executed unless the user has the **drop** privilege for the destination database\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Drop_Table = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Drop.Table',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `DROP TABLE` statements\n'
|
||||
'to be executed unless the user has the **drop** privilege for the destination database or the table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_GrantRevoke = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.GrantRevoke',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `GRANT` or `REVOKE` statements\n'
|
||||
'to be executed unless the user has the **grant option** privilege\n'
|
||||
'for the privilege of the destination table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Use = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Use',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow the `USE` statement to be executed\n'
|
||||
'unless the user has at least one of the privileges for the database\n'
|
||||
'or the table inside that database\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Admin = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Admin',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any of the following statements\n'
|
||||
'\n'
|
||||
'* `SYSTEM`\n'
|
||||
'* `SHOW`\n'
|
||||
'* `ATTACH`\n'
|
||||
'* `CHECK TABLE`\n'
|
||||
'* `DESCRIBE TABLE`\n'
|
||||
'* `DETACH`\n'
|
||||
'* `EXISTS`\n'
|
||||
'* `KILL QUERY`\n'
|
||||
'* `KILL MUTATION`\n'
|
||||
'* `OPTIMIZE`\n'
|
||||
'* `RENAME`\n'
|
||||
'* `TRUNCATE`\n'
|
||||
'\n'
|
||||
'to be executed unless the user has the **admin option** privilege\n'
|
||||
'through one of the roles with **admin option** privilege assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_PartialRevokes = Requirement(
|
||||
name='RQ.SRS-006.RBAC.PartialRevokes',
|
||||
version='1.0',
|
||||
@ -2319,52 +1996,6 @@ RQ_SRS_006_RBAC_Grant_Privilege_Select = Requirement(
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Grant.Privilege.Select.Effect',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL add the **select** privilege to the specified users or roles\n'
|
||||
'after the successful execution of the `GRANT SELECT` statement.\n'
|
||||
'Any new operation by a user or a user that has the specified role\n'
|
||||
'which requires the **select** privilege SHALL succeed.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_SelectColumns = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Grant.Privilege.SelectColumns',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting the **select columns** privilege to one or more users or roles\n'
|
||||
'for a database or a table using the `GRANT SELECT(columns)` statement.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_SelectColumns_Effect = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Grant.Privilege.SelectColumns.Effect',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL add the **select columns** privilege to the specified users or roles\n'
|
||||
'after the successful execution of the `GRANT SELECT(columns)` statement.\n'
|
||||
'Any new operation by a user or a user that has the specified role\n'
|
||||
'which requires the **select columns** privilege SHALL succeed.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Insert = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Grant.Privilege.Insert',
|
||||
version='1.0',
|
||||
@ -2375,21 +2006,9 @@ RQ_SRS_006_RBAC_Grant_Privilege_Insert = Requirement(
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting the **insert** privilege to one or more users or roles\n'
|
||||
'for a database or a table using the `GRANT INSERT` statement.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Insert_Effect = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Grant.Privilege.Insert.Effect',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL add the **insert** privilege to the specified users or roles\n'
|
||||
'after the successful execution of the `GRANT INSERT` statement.\n'
|
||||
'Any new operation by a user or a user that has the specified role\n'
|
||||
'When the **insert** privilege is granted to the specified users or roles\n'
|
||||
'after the successful execution of the `GRANT INSERT` statement,\n'
|
||||
'any new operation by a user or a user that has the specified role\n'
|
||||
'which requires the **insert** privilege SHALL succeed.\n'
|
||||
),
|
||||
link=None
|
||||
@ -2942,9 +2561,8 @@ RQ_SRS_006_RBAC_Grant_Privilege_Syntax = Requirement(
|
||||
'grants explicit privileges to a user or a role.\n'
|
||||
'\n'
|
||||
'```sql\n'
|
||||
'GRANT [ON CLUSTER cluster_name]\n'
|
||||
' privilege {SELECT | SELECT(columns) | INSERT | ALTER | CREATE | DROP | TRUNCATE | OPTIMIZE | SHOW | KILL QUERY | ACCESS MANAGEMENT | SYSTEM | INTROSPECTION | SOURCES | dictGet | NONE |ALL \t[PRIVILEGES]} [, ...]\n'
|
||||
' ON {*.* | database.* | database.table | * | table}\n'
|
||||
'GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...]\n'
|
||||
' ON {db.table|db.*|*.*|table|*}\n'
|
||||
' TO {user | role | CURRENT_USER} [,...]\n'
|
||||
' [WITH GRANT OPTION]\n'
|
||||
'```\n'
|
||||
@ -3029,22 +2647,6 @@ RQ_SRS_006_RBAC_Revoke_Privilege_Select = Requirement(
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select_Effect = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Revoke.Privilege.Select.Effect',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL remove the **select** privilege from the specified users or roles\n'
|
||||
'after the successful execution of the `REVOKE SELECT` statement.\n'
|
||||
'Any new operation by a user or a user that had the specified role\n'
|
||||
'which requires the **select** privilege SHALL fail if user does not have it otherwise.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Insert = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Revoke.Privilege.Insert',
|
||||
version='1.0',
|
||||
@ -3055,21 +2657,9 @@ RQ_SRS_006_RBAC_Revoke_Privilege_Insert = Requirement(
|
||||
description=(
|
||||
'[ClickHouse] SHALL support revoking the **insert** privilege to one or more users or roles\n'
|
||||
'for a database or a table using the `REVOKE INSERT` statement.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Insert_Effect = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Revoke.Privilege.Insert.Effect',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL remove the **insert** privilege from the specified users or roles\n'
|
||||
'after the successful execution of the `REVOKE INSERT` statement.\n'
|
||||
'Any new operation by a user or a user that had the specified role\n'
|
||||
'When the **insert** privilege is removed from the specified users or roles\n'
|
||||
'after the successful execution of the `REVOKE INSERT` statement,\n'
|
||||
'any new operation by a user or a user that had the specified role\n'
|
||||
'which requires the **insert** privilege SHALL fail if user does not have it otherwise.\n'
|
||||
),
|
||||
link=None
|
||||
@ -3664,13 +3254,6 @@ RQ_SRS_006_RBAC_Revoke_Privilege_Syntax = Requirement(
|
||||
' ON {db.table|db.*|*.*|table|*}\n'
|
||||
' FROM {user | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user | CURRENT_USER} [,...]\n'
|
||||
'```\n'
|
||||
'<!-- old syntax, for reference -->\n'
|
||||
'<!-- ```sql\n'
|
||||
'REVOKE [GRANT OPTION FOR]\n'
|
||||
' {USAGE | SELECT | SELECT(columns) | INSERT | DELETE | ALTER | CREATE | DROP | ALL [PRIVILEGES]} [, ...]\n'
|
||||
' ON {*.* | database.* | database.table | * | table}\n'
|
||||
' FROM user_or_role [, user_or_role ...]\n'
|
||||
'``` -->\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
@ -6192,3 +5775,509 @@ RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_Syntax = Requirement(
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Usage = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Usage',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **usage** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support changing access to the **select** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
'Any `SELECT INTO` statements SHALL not to be executed, unless the user\n'
|
||||
'has the **select** privilege for the destination table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Grant = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select.Grant',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting **select** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Revoke = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select.Revoke',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support revoking **select** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Column = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select.Column',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **select** privilege\n'
|
||||
'for one or more specified columns in a table to one or more **users** or **roles**.\n'
|
||||
'Any `SELECT INTO` statements SHALL not to be executed, unless the user\n'
|
||||
'has the **select** privilege for the destination column\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Cluster = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select.Cluster',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **select** privilege\n'
|
||||
'on a specified cluster to one or more **users** or **roles**.\n'
|
||||
'Any `SELECT INTO` statements SHALL succeed only on nodes where\n'
|
||||
'the table exists and privilege was granted.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select.GrantOption',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting **select** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**\n'
|
||||
'with a `GRANT OPTION` clause. User with **grant option** privilege SHALL be able to\n'
|
||||
'change access to the **select** privilege by another user or role\n'
|
||||
'on the same or smaller scope that they have access to.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Grant = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select.GrantOption.Grant',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support a user with **grant option** privilege\n'
|
||||
'granting **select** privilege to other **users** or **roles** on the same\n'
|
||||
'or smaller scope that they have access to. Any `SELECT INTO` statements SHALL succeed\n'
|
||||
'when done by a user with privilege granted by a user with `GRANT OPTION`,\n'
|
||||
'either directly or through an assigned role.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Revoke = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Select.GrantOption.Revoke',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support a user with **grant option** privilege\n'
|
||||
'revoking **select** privilege from other **users** or **roles** on the same\n'
|
||||
'or smaller scope that they have access to. Any `SELECT INTO` statements SHALL fail\n'
|
||||
'when done by a user with privilege revoke by a user with `GRANT OPTION`,\n'
|
||||
'either directly or through an assigned role, unless they have access otherwise.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support changing access to the **insert** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
'Any `INSERT INTO` statements SHALL not to be executed, unless the user\n'
|
||||
'has the **insert** privilege for the destination table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert_Grant = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert.Grant',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting **insert** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert_Revoke = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert.Revoke',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support revoking **insert** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert_Column = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert.Column',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **insert** privilege\n'
|
||||
'for one or more specified columns in a table to one or more **users** or **roles**.\n'
|
||||
'Any `INSERT INTO` statements SHALL not to be executed, unless the user\n'
|
||||
'has the **insert** privilege for the destination column\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert_Cluster = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert.Cluster',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **insert** privilege\n'
|
||||
'on a specified cluster to one or more **users** or **roles**.\n'
|
||||
'Any `INSERT INTO` statements SHALL succeed only on nodes where\n'
|
||||
'the table exists and privilege was granted.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert_GrantOption = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert.GrantOption',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting **insert** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**\n'
|
||||
'with a `GRANT OPTION` clause. User with **grant option** privilege SHALL be able to\n'
|
||||
'change access to the **insert** privilege by another user or role\n'
|
||||
'on the same or smaller scope that they have access to.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert_GrantOption_Grant = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert.GrantOption.Grant',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support a user with **grant option** privilege\n'
|
||||
'granting **insert** privilege to other **users** or **roles** on the same\n'
|
||||
'or smaller scope that they have access to. Any `INSERT INTO` statements SHALL succeed\n'
|
||||
'when done by a user with privilege granted by a user with `GRANT OPTION`,\n'
|
||||
'either directly or through an assigned role.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Insert_GrantOption_Revoke = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Insert.GrantOption.Revoke',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support a user with **grant option** privilege\n'
|
||||
'revoking **insert** privilege from other **users** or **roles** on the same\n'
|
||||
'or smaller scope that they have access to. Any `INSERT INTO` statements SHALL fail\n'
|
||||
'when done by a user with privilege revoke by a user with `GRANT OPTION`,\n'
|
||||
'either directly or through an assigned role, unless they have access otherwise.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Delete = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Delete',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **delete** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Alter = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Alter',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **alter** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Create = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Create',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **create** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_Drop = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.Drop',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **drop** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_All = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.All',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL include in the **all** privilege the same rights\n'
|
||||
'as provided by **usage**, **select**, **select columns**,\n'
|
||||
'**insert**, **delete**, **alter**, **create**, and **drop** privileges.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_All_GrantRevoke = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.All.GrantRevoke',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **all** privileges\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_GrantOption = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.GrantOption',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **grant option** privilege\n'
|
||||
'for a database or a specific table to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_Privileges_AdminOption = Requirement(
|
||||
name='RQ.SRS-006.RBAC.Privileges.AdminOption',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL support granting or revoking **admin option** privilege\n'
|
||||
'to one or more **users** or **roles**.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Create = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Create',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `CREATE` statements\n'
|
||||
'to be executed unless the user has the **create** privilege for the destination database\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Alter = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Alter',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `ALTER` statements\n'
|
||||
'to be executed unless the user has the **alter** privilege for the destination table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Drop = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Drop',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `DROP` statements\n'
|
||||
'to be executed unless the user has the **drop** privilege for the destination database\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Drop_Table = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Drop.Table',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `DROP TABLE` statements\n'
|
||||
'to be executed unless the user has the **drop** privilege for the destination database or the table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_GrantRevoke = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.GrantRevoke',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any `GRANT` or `REVOKE` statements\n'
|
||||
'to be executed unless the user has the **grant option** privilege\n'
|
||||
'for the privilege of the destination table\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Use = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Use',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow the `USE` statement to be executed\n'
|
||||
'unless the user has at least one of the privileges for the database\n'
|
||||
'or the table inside that database\n'
|
||||
'either because of the explicit grant or through one of the roles assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Admin = Requirement(
|
||||
name='RQ.SRS-006.RBAC.RequiredPrivileges.Admin',
|
||||
version='1.0',
|
||||
priority=None,
|
||||
group=None,
|
||||
type=None,
|
||||
uid=None,
|
||||
description=(
|
||||
'[ClickHouse] SHALL not allow any of the following statements\n'
|
||||
'\n'
|
||||
'* `SYSTEM`\n'
|
||||
'* `SHOW`\n'
|
||||
'* `ATTACH`\n'
|
||||
'* `CHECK TABLE`\n'
|
||||
'* `DESCRIBE TABLE`\n'
|
||||
'* `DETACH`\n'
|
||||
'* `EXISTS`\n'
|
||||
'* `KILL QUERY`\n'
|
||||
'* `KILL MUTATION`\n'
|
||||
'* `OPTIMIZE`\n'
|
||||
'* `RENAME`\n'
|
||||
'* `TRUNCATE`\n'
|
||||
'\n'
|
||||
'to be executed unless the user has the **admin option** privilege\n'
|
||||
'through one of the roles with **admin option** privilege assigned to the user.\n'
|
||||
),
|
||||
link=None
|
||||
)
|
||||
|
@ -3,5 +3,4 @@ from testflows.core import *
|
||||
@TestFeature
|
||||
@Name("privileges")
|
||||
def feature(self):
|
||||
Feature(run=load("rbac.tests.privileges.insert", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.privileges.select", "feature"), flags=TE)
|
||||
|
@ -12,8 +12,6 @@ table_types = {
|
||||
"CollapsingMergeTree": "CREATE TABLE {name} (d Date, a String, b UInt8, x String, y Int8, z UInt32) ENGINE = CollapsingMergeTree(d, (a, b), 111, y);"
|
||||
}
|
||||
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
|
||||
@contextmanager
|
||||
def table(node, name, table_type="MergeTree"):
|
||||
try:
|
||||
@ -44,70 +42,47 @@ def role(node, role):
|
||||
with Finally("I drop the role"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
|
||||
def input_output_equality_check(node, user, input_columns="d", input_data="2020-01-01"):
|
||||
"""
|
||||
ensures that selecting some data from a specified user on some table gives the desired
|
||||
result. The desired result is specified from input_columns and input_data
|
||||
"""
|
||||
data_list = [x.strip("'") for x in input_data.split(",")]
|
||||
input_dict = dict(zip(input_columns.split(","), data_list))
|
||||
output_dict = json.loads(node.query(f"select {input_columns} from merge_tree format JSONEachRow",
|
||||
settings = [("user", user)]).output)
|
||||
output_dict = {k:str(v) for (k,v) in output_dict.items()}
|
||||
return input_dict == output_dict
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0")
|
||||
)
|
||||
def without_privilege(self, table_type, node=None):
|
||||
"""Check that user without select privilege on a table is not able to select on that table."""
|
||||
"""Check that user without select privilege on a table is not able to select on that table.
|
||||
"""
|
||||
if node is None:
|
||||
node = self.context.node
|
||||
with table(node, "merge_tree", table_type):
|
||||
with user(node, "user0"):
|
||||
with When("I run SELECT without privilege"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query("SELECT * FROM merge_tree", settings = [("user","user0")],
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0")
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Grant("1.0"),
|
||||
)
|
||||
def user_with_privilege(self, table_type, node=None):
|
||||
"""Check that user can select from a table on which they have select privilege."""
|
||||
"""Check that user can select from a table on which they have select privilege.
|
||||
"""
|
||||
if node is None:
|
||||
node = self.context.node
|
||||
with table(node, "merge_tree", table_type):
|
||||
with Given("I have some data inserted into table"):
|
||||
node.query("INSERT INTO merge_tree (d) VALUES ('2020-01-01')")
|
||||
with user(node, "user88"):
|
||||
pass
|
||||
with user(node, "user0"):
|
||||
with When("I grant privilege"):
|
||||
node.query("GRANT SELECT ON merge_tree TO user0")
|
||||
with And("I use SELECT"):
|
||||
node.query("SELECT d FROM merge_tree", settings = [("user","user0")])
|
||||
with Then("I check the SELECT call output is correct"):
|
||||
assert input_output_equality_check(node, "user0"), error()
|
||||
with Then("I verify SELECT command"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user0")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output, error()
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_On_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From_Effect("1.0")
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Revoke("1.0"),
|
||||
)
|
||||
def user_with_revoked_privilege(self, table_type, node=None):
|
||||
"""
|
||||
Check that user is unable to select from a table after select privilege
|
||||
"""Check that user is unable to select from a table after select privilege
|
||||
on that table has been revoked from the user.
|
||||
"""
|
||||
if node is None:
|
||||
@ -119,25 +94,19 @@ def user_with_revoked_privilege(self, table_type, node=None):
|
||||
with And("I revoke privilege"):
|
||||
node.query("REVOKE SELECT ON merge_tree FROM user0")
|
||||
with And("I use SELECT, throws exception"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query("SELECT * FROM merge_tree", settings = [("user","user0")],
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
def user_with_privilege_on_columns(self, table_type):
|
||||
Scenario(run=user_column_privileges,
|
||||
examples=Examples("grant_columns revoke_columns select_columns_fail select_columns_pass data_pass table_type",
|
||||
[tuple(list(row)+[table_type]) for row in user_column_privileges.examples]))
|
||||
|
||||
@TestOutline(Scenario)
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_PrivelegeColumns("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_PrivelegeColumns_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_On_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From_Effect("1.0")
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Column("1.0"),
|
||||
)
|
||||
@Examples("grant_columns revoke_columns select_columns_fail select_columns_pass data_pass", [
|
||||
("d", "d", "x", "d", '\'2020-01-01\''),
|
||||
@ -145,9 +114,8 @@ def user_with_revoked_privilege(self, table_type, node=None):
|
||||
("d,a,b", "d,a,b", "x", "d,b", '\'2020-01-01\',9'),
|
||||
("d,a,b", "b", "y", "d,a,b", '\'2020-01-01\',\'woo\',9')
|
||||
])
|
||||
def user_with_privilege_on_columns(self, grant_columns, select_columns_pass, data_pass, table_type, revoke_columns=None, select_columns_fail=None, node=None):
|
||||
"""
|
||||
Check that user is able to select on granted columns
|
||||
def user_column_privileges(self, grant_columns, select_columns_pass, data_pass, table_type, revoke_columns=None, select_columns_fail=None, node=None):
|
||||
"""Check that user is able to select on granted columns
|
||||
and unable to select on not granted or revoked columns.
|
||||
"""
|
||||
if node is None:
|
||||
@ -159,28 +127,26 @@ def user_with_privilege_on_columns(self, grant_columns, select_columns_pass, dat
|
||||
node.query(f"GRANT SELECT({grant_columns}) ON merge_tree TO user0")
|
||||
if select_columns_fail is not None:
|
||||
with And("I select from not granted column"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query(f"SELECT ({select_columns_fail}) FROM merge_tree",
|
||||
settings = [("user","user0")], exitcode=exitcode, message=message)
|
||||
with Then("I select from granted column and check result"):
|
||||
assert input_output_equality_check(node, "user0", input_columns=select_columns_pass, input_data=data_pass), error()
|
||||
with Then("I select from granted column, verify correct result"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user0")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output
|
||||
if revoke_columns is not None:
|
||||
with When("I revoke select privilege for columns from user"):
|
||||
node.query(f"REVOKE SELECT({revoke_columns}) ON merge_tree FROM user0")
|
||||
with And("I select from revoked columns"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query(f"SELECT ({select_columns_pass}) FROM merge_tree", settings = [("user","user0")], exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0")
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Grant("1.0"),
|
||||
)
|
||||
def role_with_privilege(self, table_type, node=None):
|
||||
"""
|
||||
Check that user can select from a table after it is granted a role that
|
||||
"""Check that user can select from a table after it is granted a role that
|
||||
has the select privilege for that table.
|
||||
"""
|
||||
if node is None:
|
||||
@ -194,23 +160,17 @@ def role_with_privilege(self, table_type, node=None):
|
||||
node.query("GRANT SELECT ON merge_tree TO role0")
|
||||
with And("I grant role to the user"):
|
||||
node.query("GRANT role0 TO user0")
|
||||
with Then("I check that SELECT call output is correct"):
|
||||
assert input_output_equality_check(node, "user0"), error()
|
||||
with Then("I verify SELECT command"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user0")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output, error()
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_On_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From_Effect("1.0")
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Revoke("1.0"),
|
||||
)
|
||||
def role_with_revoked_privilege(self, table_type, node=None):
|
||||
"""
|
||||
Check that user with a role that has select privilege on a table is unable
|
||||
"""Check that user with a role that has select privilege on a table is unable
|
||||
to select from that table after select privilege has been revoked from the role.
|
||||
"""
|
||||
if node is None:
|
||||
@ -224,23 +184,13 @@ def role_with_revoked_privilege(self, table_type, node=None):
|
||||
with And("I revoke privilege from the role"):
|
||||
node.query("REVOKE SELECT ON merge_tree FROM role0")
|
||||
with And("I select from the table"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query("SELECT * FROM merge_tree", settings = [("user","user0")],
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Effect("1.0")
|
||||
)
|
||||
def user_with_revoked_role(self, table_type, node=None):
|
||||
"""
|
||||
Check that user with a role that has select privilege on a table is unable to
|
||||
"""Check that user with a role that has select privilege on a table is unable to
|
||||
select from that table after the role with select privilege has been revoked from the user.
|
||||
"""
|
||||
if node is None:
|
||||
@ -254,25 +204,19 @@ def user_with_revoked_role(self, table_type, node=None):
|
||||
with And("I revoke the role from the user"):
|
||||
node.query("REVOKE role0 FROM user0")
|
||||
with And("I select from the table"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query("SELECT * FROM merge_tree", settings = [("user","user0")],
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
def role_with_privilege_on_columns(self, table_type):
|
||||
Scenario(run=role_column_privileges,
|
||||
examples=Examples("grant_columns revoke_columns select_columns_fail select_columns_pass data_pass table_type",
|
||||
[tuple(list(row)+[table_type]) for row in role_column_privileges.examples]))
|
||||
|
||||
@TestOutline(Scenario)
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_PrivelegeColumns("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_PrivelegeColumns_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_On_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From_Effect("1.0")
|
||||
RQ_SRS_006_RBAC_Privileges_Select_Column("1.0"),
|
||||
)
|
||||
@Examples("grant_columns revoke_columns select_columns_fail select_columns_pass data_pass", [
|
||||
("d", "d", "x", "d", '\'2020-01-01\''),
|
||||
@ -280,9 +224,8 @@ def user_with_revoked_role(self, table_type, node=None):
|
||||
("d,a,b", "d,a,b", "x", "d,b", '\'2020-01-01\',9'),
|
||||
("d,a,b", "b", "y", "d,a,b", '\'2020-01-01\',\'woo\',9')
|
||||
])
|
||||
def role_with_privilege_on_columns(self, grant_columns, select_columns_pass, data_pass, table_type, revoke_columns=None, select_columns_fail=None, node=None):
|
||||
"""
|
||||
Check that user is able to select from granted columns and unable
|
||||
def role_column_privileges(self, grant_columns, select_columns_pass, data_pass, table_type, revoke_columns=None, select_columns_fail=None, node=None):
|
||||
"""Check that user is able to select from granted columns and unable
|
||||
to select from not granted or revoked columns.
|
||||
"""
|
||||
if node is None:
|
||||
@ -297,29 +240,27 @@ def role_with_privilege_on_columns(self, grant_columns, select_columns_pass, dat
|
||||
node.query("GRANT role0 TO user0")
|
||||
if select_columns_fail is not None:
|
||||
with And("I select from not granted column"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query(f"SELECT ({select_columns_fail}) FROM merge_tree",
|
||||
settings = [("user","user0")], exitcode=exitcode, message=message)
|
||||
with Then("I select from granted column and check result"):
|
||||
assert input_output_equality_check(node, "user0", input_columns=select_columns_pass, input_data=data_pass), error()
|
||||
with Then("I verify SELECT command"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user0")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output, error()
|
||||
if revoke_columns is not None:
|
||||
with When("I revoke select privilege for columns from role"):
|
||||
node.query(f"REVOKE SELECT({revoke_columns}) ON merge_tree FROM role0")
|
||||
with And("I select from revoked columns"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query(f"SELECT ({select_columns_pass}) FROM merge_tree",
|
||||
settings = [("user","user0")], exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Grant("1.0"),
|
||||
)
|
||||
def user_with_privilege_on_cluster(self, table_type, node=None):
|
||||
"""
|
||||
Check that user is able to select from a table with
|
||||
"""Check that user is able to select from a table with
|
||||
privilege granted on a cluster.
|
||||
"""
|
||||
if node is None:
|
||||
@ -332,24 +273,20 @@ def user_with_privilege_on_cluster(self, table_type, node=None):
|
||||
node.query("CREATE USER OR REPLACE user0 ON CLUSTER sharded_cluster")
|
||||
with When("I grant select privilege on a cluster"):
|
||||
node.query("GRANT ON CLUSTER sharded_cluster SELECT ON merge_tree TO user0")
|
||||
with Then("I check that SELECT call output is correct"):
|
||||
assert input_output_equality_check(node, "user0"), error()
|
||||
with Then("I verify SELECT command"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user0")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output, error()
|
||||
finally:
|
||||
with Finally("I drop the user"):
|
||||
node.query("DROP USER user0 ON CLUSTER sharded_cluster")
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Grant("1.0"),
|
||||
)
|
||||
def user_with_privilege_from_user_with_grant_option(self, table_type, node=None):
|
||||
"""
|
||||
Check that user is able to select from a table when granted privilege
|
||||
"""Check that user is able to select from a table when granted privilege
|
||||
from another user with grant option.
|
||||
"""
|
||||
if node is None:
|
||||
@ -362,21 +299,17 @@ def user_with_privilege_from_user_with_grant_option(self, table_type, node=None)
|
||||
node.query("GRANT SELECT ON merge_tree TO user0 WITH GRANT OPTION")
|
||||
with And("I grant privilege to another user via grant option"):
|
||||
node.query("GRANT SELECT ON merge_tree TO user1", settings = [("user","user0")])
|
||||
with Then("I check that SELECT call output is correct"):
|
||||
assert input_output_equality_check(node, "user1"), error()
|
||||
with Then("I verify SELECT command"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user1")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output, error()
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Grant("1.0"),
|
||||
)
|
||||
def role_with_privilege_from_user_with_grant_option(self, table_type, node=None):
|
||||
"""
|
||||
Check that user is able to select from a table when granted a role with
|
||||
"""Check that user is able to select from a table when granted a role with
|
||||
select privilege that was granted by another user with grant option.
|
||||
"""
|
||||
if node is None:
|
||||
@ -391,21 +324,17 @@ def role_with_privilege_from_user_with_grant_option(self, table_type, node=None)
|
||||
node.query("GRANT SELECT ON merge_tree TO role0", settings = [("user","user0")])
|
||||
with And("I grant the role to another user"):
|
||||
node.query("GRANT role0 TO user1")
|
||||
with Then("I check that SELECT call output is correct"):
|
||||
assert input_output_equality_check(node, "user1"), error()
|
||||
with Then("I verify SELECT command"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user1")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output, error()
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Grant("1.0"),
|
||||
)
|
||||
def user_with_privilege_from_role_with_grant_option(self, table_type, node=None):
|
||||
"""
|
||||
Check that user is able to select from a table when granted privilege from
|
||||
"""Check that user is able to select from a table when granted privilege from
|
||||
a role with grant option
|
||||
"""
|
||||
if node is None:
|
||||
@ -420,21 +349,17 @@ def user_with_privilege_from_role_with_grant_option(self, table_type, node=None)
|
||||
node.query("GRANT role0 TO user0")
|
||||
with And("I grant privilege to a user via grant option"):
|
||||
node.query("GRANT SELECT ON merge_tree TO user1", settings = [("user","user0")])
|
||||
with Then("I check that SELECT call output is correct"):
|
||||
assert input_output_equality_check(node, "user1"), error()
|
||||
with Then("I verify SELECT command"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user1")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output, error()
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Grant("1.0"),
|
||||
)
|
||||
def role_with_privilege_from_role_with_grant_option(self, table_type, node=None):
|
||||
"""
|
||||
Check that a user is able to select from a table with a role that was
|
||||
"""Check that a user is able to select from a table with a role that was
|
||||
granted privilege by another role with grant option
|
||||
"""
|
||||
if node is None:
|
||||
@ -451,22 +376,18 @@ def role_with_privilege_from_role_with_grant_option(self, table_type, node=None)
|
||||
node.query("GRANT SELECT ON merge_tree TO role1", settings = [("user","user0")])
|
||||
with And("I grant the second role to another user"):
|
||||
node.query("GRANT role1 TO user1")
|
||||
with Then("I check that SELECT call output is correct"):
|
||||
assert input_output_equality_check(node, "user1"), error()
|
||||
with Then("I verify SELECT command"):
|
||||
user_select = node.query("SELECT d FROM merge_tree", settings = [("user","user1")])
|
||||
default = node.query("SELECT d FROM merge_tree")
|
||||
assert user_select.output == default.output, error()
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_GrantOption("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_PrivilegeColumns("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Revoke("1.0"),
|
||||
)
|
||||
def revoke_privilege_from_user_via_user_with_grant_option(self, table_type, node=None):
|
||||
"""Check that user is unable to revoke a column they don't have access to from a user."""
|
||||
"""Check that user is unable to revoke a column they don't have access to from a user.
|
||||
"""
|
||||
if node is None:
|
||||
node = self.context.node
|
||||
with table(node, "merge_tree", table_type):
|
||||
@ -474,22 +395,17 @@ def revoke_privilege_from_user_via_user_with_grant_option(self, table_type, node
|
||||
with When("I grant privilege with grant option to user"):
|
||||
node.query("GRANT SELECT(d) ON merge_tree TO user0 WITH GRANT OPTION")
|
||||
with Then("I revoke privilege on a column the user with grant option does not have access to"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query("REVOKE SELECT(b) ON merge_tree FROM user1", settings=[("user","user0")],
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_GrantOption("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_PrivilegeColumns("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Revoke("1.0"),
|
||||
)
|
||||
def revoke_privilege_from_role_via_user_with_grant_option(self, table_type, node=None):
|
||||
"""Check that user is unable to revoke a column they dont have acces to from a role."""
|
||||
"""Check that user is unable to revoke a column they dont have acces to from a role.
|
||||
"""
|
||||
if node is None:
|
||||
node = self.context.node
|
||||
with table(node, "merge_tree", table_type):
|
||||
@ -497,22 +413,17 @@ def revoke_privilege_from_role_via_user_with_grant_option(self, table_type, node
|
||||
with When("I grant privilege with grant option to user"):
|
||||
node.query("GRANT SELECT(d) ON merge_tree TO user0 WITH GRANT OPTION")
|
||||
with Then("I revoke privilege on a column the user with grant option does not have access to"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query("REVOKE SELECT(b) ON merge_tree FROM role0", settings=[("user","user0")],
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_GrantOption("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_PrivilegeColumns("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Revoke("1.0"),
|
||||
)
|
||||
def revoke_privilege_from_user_via_role_with_grant_option(self, table_type, node=None):
|
||||
"""Check that user with a role is unable to revoke a column they dont have acces to from a user."""
|
||||
"""Check that user with a role is unable to revoke a column they dont have acces to from a user.
|
||||
"""
|
||||
if node is None:
|
||||
node = self.context.node
|
||||
with table(node, "merge_tree", table_type):
|
||||
@ -522,22 +433,17 @@ def revoke_privilege_from_user_via_role_with_grant_option(self, table_type, node
|
||||
with And("I grant the role to a user"):
|
||||
node.query("GRANT role0 TO user0")
|
||||
with Then("I revoke privilege on a column the user with grant option does not have access to"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query("REVOKE SELECT(b) ON merge_tree FROM user1", settings=[("user","user0")],
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
@TestScenario
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_GrantOption("1.0"),
|
||||
RQ_SRS_006_RBAC_RequiredPrivileges_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To_Effect("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_On("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_PrivilegeColumns("1.0"),
|
||||
RQ_SRS_006_RBAC_Privileges_Select_GrantOption_Revoke("1.0"),
|
||||
)
|
||||
def revoke_privilege_from_role_via_role_with_grant_option(self, table_type, node=None):
|
||||
"""Check that user with a role is unable to revoke a column they dont have acces to from a role."""
|
||||
"""Check that user with a role is unable to revoke a column they dont have acces to from a role.
|
||||
"""
|
||||
if node is None:
|
||||
node = self.context.node
|
||||
with table(node, "merge_tree", table_type):
|
||||
@ -547,10 +453,14 @@ def revoke_privilege_from_role_via_role_with_grant_option(self, table_type, node
|
||||
with And("I grant the role to a user"):
|
||||
node.query("GRANT role0 TO user0")
|
||||
with Then("I revoke privilege on a column the user with grant option does not have access to"):
|
||||
exitcode, message = errors.not_enough_privileges(name="user0")
|
||||
node.query("REVOKE SELECT(b) ON merge_tree FROM role1", settings=[("user","user0")],
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
@TestOutline(Feature)
|
||||
@Requirements(
|
||||
RQ_SRS_006_RBAC_Privileges_Select("1.0"),
|
||||
)
|
||||
@Examples("table_type", [
|
||||
(key,) for key in table_types.keys()
|
||||
])
|
||||
@ -561,15 +471,11 @@ def feature(self, table_type, node="clickhouse1"):
|
||||
Scenario(test=without_privilege)(table_type=table_type)
|
||||
Scenario(test=user_with_privilege)(table_type=table_type)
|
||||
Scenario(test=user_with_revoked_privilege)(table_type=table_type)
|
||||
Scenario(run=user_with_privilege_on_columns,
|
||||
examples=Examples("grant_columns revoke_columns select_columns_fail select_columns_pass data_pass table_type",
|
||||
[tuple(list(row)+[table_type]) for row in user_with_privilege_on_columns.examples]))
|
||||
Scenario(test=user_with_privilege_on_columns)(table_type=table_type)
|
||||
Scenario(test=role_with_privilege)(table_type=table_type)
|
||||
Scenario(test=role_with_revoked_privilege)(table_type=table_type)
|
||||
Scenario(test=user_with_revoked_role)(table_type=table_type)
|
||||
Scenario(run=role_with_privilege_on_columns,
|
||||
examples=Examples("grant_columns revoke_columns select_columns_fail select_columns_pass data_pass table_type",
|
||||
[tuple(list(row)+[table_type]) for row in role_with_privilege_on_columns.examples]))
|
||||
Scenario(test=role_with_privilege_on_columns)(table_type=table_type)
|
||||
Scenario(test=user_with_privilege_on_cluster)(table_type=table_type)
|
||||
Scenario(test=user_with_privilege_from_user_with_grant_option)(table_type=table_type)
|
||||
Scenario(test=role_with_privilege_from_user_with_grant_option)(table_type=table_type)
|
||||
@ -578,4 +484,4 @@ def feature(self, table_type, node="clickhouse1"):
|
||||
Scenario(test=revoke_privilege_from_user_via_user_with_grant_option)(table_type=table_type)
|
||||
Scenario(test=revoke_privilege_from_role_via_user_with_grant_option)(table_type=table_type)
|
||||
Scenario(test=revoke_privilege_from_user_via_role_with_grant_option)(table_type=table_type)
|
||||
Scenario(test=revoke_privilege_from_role_via_role_with_grant_option)(table_type=table_type)
|
||||
Scenario(test=revoke_privilege_from_role_via_role_with_grant_option)(table_type=table_type)
|
0
tests/testflows/rbac/tests/syntax/__init__.py
Executable file
0
tests/testflows/rbac/tests/syntax/__init__.py
Executable file
206
tests/testflows/rbac/tests/syntax/alter_quota.py
Executable file
206
tests/testflows/rbac/tests/syntax/alter_quota.py
Executable file
@ -0,0 +1,206 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("alter quota")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check alter quota query syntax.
|
||||
|
||||
```sql
|
||||
ALTER QUOTA [IF EXISTS] name [ON CLUSTER cluster_name]
|
||||
[RENAME TO new_name]
|
||||
[KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
||||
[FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY | MONTH}
|
||||
{MAX { {QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = number } [,...] |
|
||||
NO LIMITS | TRACKING ONLY} [,...]]
|
||||
[TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
def cleanup_quota(quota):
|
||||
with Given(f"I ensure that quota {quota} does not exist"):
|
||||
node.query(f"DROP QUOTA IF EXISTS {quota}")
|
||||
|
||||
try:
|
||||
with Given("I have a quota, a user, and a role"):
|
||||
node.query(f"CREATE QUOTA quota0")
|
||||
node.query(f"CREATE USER user0")
|
||||
node.query(f"CREATE ROLE role0")
|
||||
|
||||
with Scenario("I alter quota with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter("1.0")]):
|
||||
with When("I alter quota"):
|
||||
node.query("ALTER QUOTA quota0")
|
||||
|
||||
with Scenario("I alter quota that does not exist, throws an exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter("1.0")]):
|
||||
quota = "quota1"
|
||||
cleanup_quota(quota)
|
||||
with When(f"I alter quota {quota}, which does not exist"):
|
||||
exitcode, message = errors.quota_not_found_in_disk(name=quota)
|
||||
node.query(f"ALTER QUOTA {quota}", exitcode=exitcode, message=message)
|
||||
del quota
|
||||
|
||||
with Scenario("I alter quota with if exists, quota does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_IfExists("1.0")]):
|
||||
node.query("ALTER QUOTA IF EXISTS quota0")
|
||||
|
||||
with Scenario("I alter quota with if exists, quota does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_IfExists("1.0")]):
|
||||
quota = "quota1"
|
||||
cleanup_quota(quota)
|
||||
with When(f"I alter quota {quota}, which does not exist, with IF EXISTS"):
|
||||
node.query(f"ALTER QUOTA IF EXISTS {quota}")
|
||||
del quota
|
||||
|
||||
with Scenario("I alter quota using rename, target available", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Rename("1.0")]):
|
||||
node.query("ALTER QUOTA quota0 RENAME TO quota0")
|
||||
|
||||
with Scenario("I alter quota using rename, target unavailable", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Rename("1.0")]):
|
||||
new_quota = "quota1"
|
||||
|
||||
try:
|
||||
with Given(f"Ensure target name {new_quota} is NOT available"):
|
||||
node.query(f"CREATE QUOTA IF NOT EXISTS {new_quota}")
|
||||
|
||||
with When(f"I try to rename to {new_quota}"):
|
||||
exitcode, message = errors.cannot_rename_quota(name="quota0", name_new=new_quota)
|
||||
node.query(f"ALTER QUOTA quota0 RENAME TO {new_quota}", exitcode=exitcode, message=message)
|
||||
finally:
|
||||
with Finally(f"I cleanup target name {new_quota}"):
|
||||
node.query(f"DROP QUOTA IF EXISTS {new_quota}")
|
||||
|
||||
del new_quota
|
||||
|
||||
keys = ['none', 'user name', 'ip address', 'client key', 'client key or user name', 'client key or ip address']
|
||||
for key in keys:
|
||||
with Scenario(f"I alter quota keyed by {key}", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_KeyedBy("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_KeyedByOptions("1.0")]):
|
||||
with When("I alter quota with a key"):
|
||||
node.query(f"ALTER QUOTA quota0 KEYED BY '{key}'")
|
||||
|
||||
with Scenario("I alter quota for randomized interval", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Interval_Randomized("1.0")]):
|
||||
with When("I alter quota on a randomized interval"):
|
||||
node.query("ALTER QUOTA quota0 FOR RANDOMIZED INTERVAL 1 DAY NO LIMITS")
|
||||
|
||||
intervals = ['SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH']
|
||||
for i, interval in enumerate(intervals):
|
||||
with Scenario(f"I alter quota for interval {interval}", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Interval("1.0")]):
|
||||
with When(f"I alter quota for {interval}"):
|
||||
node.query(f"ALTER QUOTA quota0 FOR INTERVAL 1 {interval} NO LIMITS")
|
||||
|
||||
constraints = ['MAX QUERIES', 'MAX ERRORS', 'MAX RESULT ROWS',
|
||||
'MAX RESULT BYTES', 'MAX READ ROWS', 'MAX READ BYTES', 'MAX EXECUTION TIME',
|
||||
'NO LIMITS', 'TRACKING ONLY']
|
||||
for i, constraint in enumerate(constraints):
|
||||
with Scenario(f"I alter quota for {constraint.lower()}", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Queries("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Errors("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_ResultRows("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_ReadRows("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_ALter_ResultBytes("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_ReadBytes("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_ExecutionTime("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_NoLimits("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_TrackingOnly("1.0")]):
|
||||
with When("I alter quota for a constraint"):
|
||||
node.query(f"ALTER QUOTA quota0 FOR INTERVAL 1 DAY {constraint}{' 1024' if constraint.startswith('MAX') else ''}")
|
||||
|
||||
with Scenario("I create quota for multiple constraints", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Interval("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Queries("1.0")]):
|
||||
node.query("ALTER QUOTA quota0 \
|
||||
FOR INTERVAL 1 DAY NO LIMITS, \
|
||||
FOR INTERVAL 2 DAY MAX QUERIES 124, \
|
||||
FOR INTERVAL 1 MONTH TRACKING ONLY")
|
||||
|
||||
with Scenario("I alter quota to assign to one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Assignment("1.0")]):
|
||||
with When("I alter quota to a role"):
|
||||
node.query("ALTER QUOTA quota0 TO role0")
|
||||
|
||||
with Scenario("I alter quota to assign to role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Assignment("1.0")]):
|
||||
role = "role1"
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I alter a quota, assign to role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"ALTER QUOTA quota0 TO {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter quota to assign to all except role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Assignment("1.0")]):
|
||||
role = "role1"
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I alter a quota, assign to all except role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"ALTER QUOTA quota0 TO ALL EXCEPT {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter quota to assign to one role and one user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Assignment("1.0")]):
|
||||
with When("I alter quota to a role and a user"):
|
||||
node.query("ALTER QUOTA quota0 TO role0, user0")
|
||||
|
||||
with Scenario("I alter quota assigned to none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Assignment_None("1.0")]):
|
||||
with When("I alter quota to none"):
|
||||
node.query("ALTER QUOTA quota0 TO NONE")
|
||||
|
||||
with Scenario("I alter quota to assign to all", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Assignment_All("1.0")]):
|
||||
with When("I alter quota to all"):
|
||||
node.query("ALTER QUOTA quota0 TO ALL")
|
||||
|
||||
with Scenario("I alter quota to assign to all except one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Assignment_Except("1.0")]):
|
||||
with When("I alter quota to all except one role"):
|
||||
node.query("ALTER QUOTA quota0 TO ALL EXCEPT role0")
|
||||
|
||||
with Scenario("I alter quota to assign to all except multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Assignment_Except("1.0")]):
|
||||
with When("I alter quota to all except one multiple roles"):
|
||||
node.query("ALTER QUOTA quota0 TO ALL EXCEPT role0, user0")
|
||||
|
||||
with Scenario("I alter quota on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Cluster("1.0")]):
|
||||
try:
|
||||
with Given("I have a quota on a cluster"):
|
||||
node.query("CREATE QUOTA quota1 ON CLUSTER sharded_cluster")
|
||||
|
||||
with When("I run alter quota command on a cluster"):
|
||||
node.query("ALTER QUOTA quota1 ON CLUSTER sharded_cluster")
|
||||
with And("I run alter quota command on a cluster with a key"):
|
||||
node.query("ALTER QUOTA quota1 ON CLUSTER sharded_cluster KEYED BY 'none'")
|
||||
with And("I run alter quota command on a cluster with an interval"):
|
||||
node.query("ALTER QUOTA quota1 ON CLUSTER sharded_cluster FOR INTERVAL 1 DAY TRACKING ONLY")
|
||||
with And("I run alter quota command on a cluster for all"):
|
||||
node.query("ALTER QUOTA quota1 ON CLUSTER sharded_cluster TO ALL")
|
||||
finally:
|
||||
with Finally("I drop the quota"):
|
||||
node.query("DROP QUOTA IF EXISTS quota1 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I alter quota on nonexistent cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Alter_Cluster("1.0")]):
|
||||
with When("I run alter quota on a cluster"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("ALTER QUOTA quota0 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
||||
|
||||
finally:
|
||||
with Finally("I drop the quota and all the users and roles"):
|
||||
node.query(f"DROP QUOTA IF EXISTS quota0")
|
||||
node.query(f"DROP USER IF EXISTS user0")
|
||||
node.query(f"DROP ROLE IF EXISTS role0")
|
196
tests/testflows/rbac/tests/syntax/alter_role.py
Executable file
196
tests/testflows/rbac/tests/syntax/alter_role.py
Executable file
@ -0,0 +1,196 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("alter role")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check alter role query syntax.
|
||||
|
||||
```sql
|
||||
ALTER ROLE [IF EXISTS] name [ON CLUSTER cluster_name]
|
||||
[RENAME TO new_name]
|
||||
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(role, profile=None):
|
||||
try:
|
||||
with Given("I have a role"):
|
||||
node.query(f"CREATE ROLE OR REPLACE {role}")
|
||||
if profile != None: #create profile when name is given
|
||||
with Given("And I have a profile"):
|
||||
node.query(f"CREATE SETTINGS PROFILE OR REPLACE {profile}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the role"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
if profile != "":
|
||||
with Finally("I drop the profile"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
|
||||
def cleanup_role(role):
|
||||
with Given(f"I ensure that role {role} does not exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
|
||||
with Scenario("I alter role with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter("1.0")]):
|
||||
with setup("role0"):
|
||||
with When("I alter role"):
|
||||
node.query("ALTER ROLE role0")
|
||||
|
||||
with Scenario("I alter role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter("1.0")]):
|
||||
role = "role0"
|
||||
cleanup_role(role)
|
||||
with When(f"I alter role {role} that does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"ALTER ROLE {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter role if exists, role does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_IfExists("1.0")]):
|
||||
with setup("role1"):
|
||||
with When("I alter role with if exists"):
|
||||
node.query("ALTER ROLE IF EXISTS role1")
|
||||
|
||||
with Scenario("I alter role if exists, role does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_IfExists("1.0")]):
|
||||
role = "role0"
|
||||
cleanup_role(role)
|
||||
with When(f"I alter role {role} that does not exist"):
|
||||
node.query(f"ALTER ROLE IF EXISTS {role}")
|
||||
del role
|
||||
|
||||
with Scenario("I alter role on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Cluster("1.0")]):
|
||||
try:
|
||||
with Given("I have a role on a cluster"):
|
||||
node.query("CREATE ROLE role1 ON CLUSTER sharded_cluster")
|
||||
with When("I run alter role on a cluster"):
|
||||
node.query("ALTER ROLE role1 ON CLUSTER sharded_cluster")
|
||||
with And("I rename role on a cluster"):
|
||||
node.query("ALTER ROLE role1 ON CLUSTER sharded_cluster RENAME TO role2")
|
||||
with And("I alter role with settings on a cluster"):
|
||||
node.query("ALTER ROLE role2 ON CLUSTER sharded_cluster SETTINGS max_memory_usage=10000000 READONLY")
|
||||
finally:
|
||||
with Finally("I drop the role"):
|
||||
node.query("DROP ROLE IF EXISTS role1,role2 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I alter role on nonexistent cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Cluster("1.0")]):
|
||||
with When("I run alter role on a cluster"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("ALTER ROLE role1 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I alter role to rename, new name is available", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Rename("1.0")]):
|
||||
with setup("role2"):
|
||||
new_role = "role3"
|
||||
try:
|
||||
with Given(f"Ensure target name {new_role} is available"):
|
||||
node.query(f"DROP ROLE IF EXISTS {new_role}")
|
||||
with When(f"I try to rename to {new_role}"):
|
||||
node.query(f"ALTER ROLE role2 RENAME TO {new_role}")
|
||||
finally:
|
||||
with Finally(f"I cleanup new name {new_role}"):
|
||||
node.query(f"DROP ROLE IF EXISTS {new_role}")
|
||||
del new_role
|
||||
|
||||
with Scenario("I alter role to rename, new name is not available, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Rename("1.0")]):
|
||||
with setup("role2a"):
|
||||
new_role = "role3a"
|
||||
try:
|
||||
with Given(f"Ensure target name {new_role} is NOT available"):
|
||||
node.query(f"CREATE ROLE IF NOT EXISTS {new_role}")
|
||||
with When(f"I try to rename to {new_role}"):
|
||||
exitcode, message = errors.cannot_rename_role(name="role2a", name_new=new_role)
|
||||
node.query(f"ALTER ROLE role2a RENAME TO {new_role}", exitcode=exitcode, message=message)
|
||||
finally:
|
||||
with Finally(f"I cleanup target name {new_role}"):
|
||||
node.query(f"DROP ROLE IF EXISTS {new_role}")
|
||||
del new_role
|
||||
|
||||
with Scenario("I alter role settings profile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role4"):
|
||||
with When("I alter role with settings profile"):
|
||||
node.query("ALTER ROLE role4 SETTINGS PROFILE default, max_memory_usage=10000000 READONLY")
|
||||
|
||||
with Scenario("I alter role settings profile, profile does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role4a"):
|
||||
with Given("I ensure profile profile0 does not exist"):
|
||||
node.query("DROP SETTINGS PROFILE IF EXISTS profile0")
|
||||
with When("I alter role with settings profile that does not exist"):
|
||||
exitcode, message = errors.settings_profile_not_found_in_disk("profile0")
|
||||
node.query("ALTER ROLE role4a SETTINGS PROFILE profile0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I alter role settings profile multiple", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role4b", profile="profile0"):
|
||||
with When("I alter role with multiple profiles"):
|
||||
node.query("ALTER ROLE role4b SETTINGS PROFILE default, PROFILE profile0, \
|
||||
max_memory_usage=10000000 READONLY")
|
||||
|
||||
with Scenario("I alter role settings without profile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role5"):
|
||||
with When("I alter role with settings and no profile"):
|
||||
node.query("ALTER ROLE role5 SETTINGS max_memory_usage=10000000 READONLY")
|
||||
|
||||
with Scenario("I alter role settings, variable does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role5a"):
|
||||
with When("I alter role using settings and nonexistent value"):
|
||||
exitcode, message = errors.unknown_setting("fake_setting")
|
||||
node.query("ALTER ROLE role5a SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message)
|
||||
|
||||
|
||||
with Scenario("I alter role settings without profile multiple", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role6"):
|
||||
with When("I alter role with multiple settings and no profile"):
|
||||
node.query("ALTER ROLE role6 SETTINGS max_memory_usage=10000000 READONLY, \
|
||||
max_rows_to_read MIN 20 MAX 25")
|
||||
|
||||
with Scenario("I alter role settings with multiple profiles multiple variables", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role7", profile="profile1"):
|
||||
with When("I alter role with multiple settings and profiles"):
|
||||
node.query("ALTER ROLE role7 SETTINGS PROFILE default, PROFILE profile1, \
|
||||
max_memory_usage=10000000 READONLY, max_rows_to_read MIN 20 MAX 25")
|
||||
|
||||
with Scenario("I alter role settings readonly", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role8"):
|
||||
with When("I alter role with readonly"):
|
||||
node.query("ALTER ROLE role8 SETTINGS max_memory_usage READONLY")
|
||||
|
||||
with Scenario("I alter role settings writable", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role9"):
|
||||
with When("I alter role with writable"):
|
||||
node.query("ALTER ROLE role9 SETTINGS max_memory_usage WRITABLE")
|
||||
|
||||
with Scenario("I alter role settings min, with and without = sign", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role10"):
|
||||
with When("I set min, no equals"):
|
||||
node.query("ALTER ROLE role10 SETTINGS max_memory_usage MIN 200")
|
||||
with When("I set min, yes equals"):
|
||||
node.query("ALTER ROLE role10 SETTINGS max_memory_usage MIN = 200")
|
||||
|
||||
with Scenario("I alter role settings max, with and without = sign", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Alter_Settings("1.0")]):
|
||||
with setup("role11"):
|
||||
with When("I set max, no equals"):
|
||||
node.query("ALTER ROLE role11 SETTINGS max_memory_usage MAX 2000")
|
||||
with When("I set max, yes equals"):
|
||||
node.query("ALTER ROLE role11 SETTINGS max_memory_usage MAX = 200")
|
244
tests/testflows/rbac/tests/syntax/alter_row_policy.py
Executable file
244
tests/testflows/rbac/tests/syntax/alter_row_policy.py
Executable file
@ -0,0 +1,244 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("alter row policy")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check alter row policy query syntax.
|
||||
|
||||
```sql
|
||||
ALTER [ROW] POLICY [IF EXISTS] name [ON CLUSTER cluster_name] ON [database.]table
|
||||
[RENAME TO new_name]
|
||||
[AS {PERMISSIVE | RESTRICTIVE}]
|
||||
[FOR SELECT]
|
||||
[USING {condition | NONE}][,...]
|
||||
[TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(policy):
|
||||
try:
|
||||
with Given("I have a row policy"):
|
||||
node.query(f"CREATE ROW POLICY {policy} ON default.foo")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the row policy"):
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {policy} ON default.foo")
|
||||
|
||||
def cleanup_policy(policy):
|
||||
with Given(f"I ensure that policy {policy} does not exist"):
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {policy} ON default.foo")
|
||||
|
||||
try:
|
||||
with Given("I have a table and some roles"):
|
||||
node.query(f"CREATE TABLE default.foo (x UInt64, y String) Engine=Memory")
|
||||
node.query(f"CREATE ROLE role0")
|
||||
node.query(f"CREATE ROLE role1")
|
||||
|
||||
with Scenario("I alter row policy with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy0"):
|
||||
with When("I alter row policy"):
|
||||
node.query("ALTER ROW POLICY policy0 ON default.foo")
|
||||
|
||||
with Scenario("I alter row policy using short syntax with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy1"):
|
||||
with When("I alter row policy short form"):
|
||||
node.query("ALTER POLICY policy1 ON default.foo")
|
||||
|
||||
with Scenario("I alter row policy, does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
policy = "policy2"
|
||||
cleanup_policy(policy)
|
||||
with When(f"I alter row policy {policy} that doesn't exist"):
|
||||
exitcode, message = errors.row_policy_not_found_in_disk(name=f"{policy} ON default.foo")
|
||||
node.query(f"ALTER ROW POLICY {policy} ON default.foo", exitcode=exitcode, message=message)
|
||||
del policy
|
||||
|
||||
with Scenario("I alter row policy if exists", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_IfExists("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy2"):
|
||||
with When("I alter row policy using if exists"):
|
||||
node.query("ALTER ROW POLICY IF EXISTS policy2 ON default.foo")
|
||||
|
||||
with Scenario("I alter row policy if exists, policy does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_IfExists("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
policy = "policy2"
|
||||
cleanup_policy(policy)
|
||||
with When(f"I alter row policy {policy} that doesn't exist"):
|
||||
node.query(f"ALTER ROW POLICY IF EXISTS {policy} ON default.foo")
|
||||
del policy
|
||||
|
||||
with Scenario("I alter row policy to rename, target available", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Rename("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy3"):
|
||||
with When("I alter row policy with rename"):
|
||||
node.query("ALTER ROW POLICY policy3 ON default.foo RENAME TO policy3")
|
||||
|
||||
with Scenario("I alter row policy to rename, target unavailable", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Rename("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy3"):
|
||||
new_policy = "policy4"
|
||||
try:
|
||||
with Given(f"Ensure target name {new_policy} is NOT available"):
|
||||
node.query(f"CREATE ROW POLICY IF NOT EXISTS {new_policy} ON default.foo")
|
||||
with When(f"I try to rename to {new_policy}"):
|
||||
exitcode, message = errors.cannot_rename_row_policy(name="policy3 ON default.foo",
|
||||
name_new=f"{new_policy} ON default.foo")
|
||||
node.query(f"ALTER ROW POLICY policy3 ON default.foo RENAME TO {new_policy}", exitcode=exitcode, message=message)
|
||||
finally:
|
||||
with Finally(f"I cleanup target name {new_policy}"):
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {new_policy} ON default.foo")
|
||||
del new_policy
|
||||
|
||||
with Scenario("I alter row policy to permissive", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Permissive("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy4"):
|
||||
with When("I alter row policy as permissive"):
|
||||
node.query("ALTER ROW POLICY policy4 ON default.foo AS PERMISSIVE")
|
||||
|
||||
with Scenario("I alter row policy to restrictive", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Access_Restrictive("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy5"):
|
||||
with When("I alter row policy as restrictive"):
|
||||
node.query("ALTER ROW POLICY policy5 ON default.foo AS RESTRICTIVE")
|
||||
|
||||
with Scenario("I alter row policy for select", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_ForSelect("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy6"):
|
||||
with When("I alter row policy using for select"):
|
||||
node.query("ALTER ROW POLICY policy6 ON default.foo FOR SELECT USING x > 10")
|
||||
|
||||
with Scenario("I alter row policy using condition", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Condition("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy6"):
|
||||
with When("I alter row policy wtih condition"):
|
||||
node.query("ALTER ROW POLICY policy6 ON default.foo USING x > 10")
|
||||
|
||||
with Scenario("I alter row policy using condition none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Condition_None("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy7"):
|
||||
with When("I alter row policy using no condition"):
|
||||
node.query("ALTER ROW POLICY policy7 ON default.foo USING NONE")
|
||||
|
||||
with Scenario("I alter row policy to one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy8"):
|
||||
with When("I alter row policy to a role"):
|
||||
node.query("ALTER ROW POLICY policy8 ON default.foo TO role0")
|
||||
|
||||
with Scenario("I alter row policy to assign to role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0")]):
|
||||
role = "role2"
|
||||
with cleanup("policy8a"):
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I alter a row policy, assign to role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"ALTER ROW POLICY policy8a ON default.foo TO {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter row policy to assign to all excpet role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0")]):
|
||||
role = "role2"
|
||||
with cleanup("policy8a"):
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I alter a row policy, assign to all except role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"ALTER ROW POLICY policy8a ON default.foo TO ALL EXCEPT {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter row policy assigned to multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy9"):
|
||||
with When("I alter row policy to multiple roles"):
|
||||
node.query("ALTER ROW POLICY policy9 ON default.foo TO role0, role1")
|
||||
|
||||
with Scenario("I alter row policy assigned to all", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_All("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy10"):
|
||||
with When("I alter row policy to all"):
|
||||
node.query("ALTER ROW POLICY policy10 ON default.foo TO ALL")
|
||||
|
||||
with Scenario("I alter row policy assigned to all except one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_AllExcept("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy11"):
|
||||
with When("I alter row policy to all except"):
|
||||
node.query("ALTER ROW POLICY policy11 ON default.foo TO ALL EXCEPT role0")
|
||||
|
||||
with Scenario("I alter row policy assigned to all except multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_AllExcept("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy12"):
|
||||
with When("I alter row policy to all except multiple roles"):
|
||||
node.query("ALTER ROW POLICY policy12 ON default.foo TO ALL EXCEPT role0, role1")
|
||||
|
||||
with Scenario("I alter row policy assigned to none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_Assignment_None("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with cleanup("policy12"):
|
||||
with When("I alter row policy to no assignment"):
|
||||
node.query("ALTER ROW POLICY policy12 ON default.foo TO NONE")
|
||||
|
||||
# Official syntax: ON CLUSTER cluster_name ON database.table
|
||||
# Working syntax: both orderings of ON CLUSTER and TABLE clauses work
|
||||
|
||||
with Scenario("I alter row policy on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
try:
|
||||
with Given("I have a row policy"):
|
||||
node.query("CREATE ROW POLICY policy13 ON CLUSTER sharded_cluster ON default.foo")
|
||||
with When("I run alter row policy command"):
|
||||
node.query("ALTER ROW POLICY policy13 ON CLUSTER sharded_cluster ON default.foo")
|
||||
finally:
|
||||
with Finally("I drop the row policy"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy13 ON CLUSTER sharded_cluster ON default.foo")
|
||||
|
||||
with Scenario("I alter row policy on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
with When("I run alter row policy command"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("ALTER ROW POLICY policy13 ON CLUSTER fake_cluster ON default.foo", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I alter row policy on cluster after table", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Alter_On("1.0")]):
|
||||
try:
|
||||
with Given("I have a row policy"):
|
||||
node.query("CREATE ROW POLICY policy14 ON default.foo ON CLUSTER sharded_cluster")
|
||||
with When("I run create row policy command"):
|
||||
node.query("ALTER ROW POLICY policy14 ON default.foo ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I drop the row policy"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy14 ON default.foo ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I drop the table and the roles"):
|
||||
node.query(f"DROP TABLE IF EXISTS default.foo")
|
||||
node.query(f"DROP ROLE IF EXISTS role0, role1")
|
232
tests/testflows/rbac/tests/syntax/alter_settings_profile.py
Executable file
232
tests/testflows/rbac/tests/syntax/alter_settings_profile.py
Executable file
@ -0,0 +1,232 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("alter settings profile")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check alter settings profile query syntax.
|
||||
|
||||
```sql
|
||||
ALTER SETTINGS PROFILE [IF EXISTS] name
|
||||
[ON CLUSTER cluster_name]
|
||||
[RENAME TO new_name]
|
||||
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | INHERIT 'profile_name'] [,...]
|
||||
[TO {user_or_role [,...] | NONE | ALL | ALL EXCEPT user_or_role [,...]]}
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
def cleanup_profile(profile):
|
||||
with Given(f"I ensure that profile {profile} does not exist"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
|
||||
try:
|
||||
with Given("I have a profile and some users and roles"):
|
||||
node.query(f"CREATE SETTINGS PROFILE profile0")
|
||||
node.query(f"CREATE USER user0")
|
||||
node.query(f"CREATE ROLE role0")
|
||||
|
||||
with Scenario("I alter settings profile with no options", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]):
|
||||
with When("I alter settings profile"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0")
|
||||
|
||||
with Scenario("I alter settings profile short form", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]):
|
||||
with When("I short form alter settings profile"):
|
||||
node.query("ALTER PROFILE profile0")
|
||||
|
||||
with Scenario("I alter settings profile that does not exist, throws exception", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter("1.0")]):
|
||||
profile = "profile1"
|
||||
|
||||
cleanup_profile(profile)
|
||||
with When(f"I alter settings profile {profile} that doesn't exist"):
|
||||
exitcode, message = errors.settings_profile_not_found_in_disk(name=profile)
|
||||
node.query(f"ALTER SETTINGS PROFILE {profile}", exitcode=exitcode, message=message)
|
||||
del profile
|
||||
|
||||
with Scenario("I alter settings profile if exists", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists("1.0")]):
|
||||
with When("I alter settings profile using if exists"):
|
||||
node.query("ALTER SETTINGS PROFILE IF EXISTS profile0")
|
||||
|
||||
with Scenario("I alter settings profile if exists, profile does not exist", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_IfExists("1.0")]):
|
||||
profile = "profile1"
|
||||
|
||||
cleanup_profile(profile)
|
||||
with When(f"I alter settings profile {profile} using if exists"):
|
||||
node.query(f"ALTER SETTINGS PROFILE IF EXISTS {profile}")
|
||||
|
||||
del profile
|
||||
|
||||
with Scenario("I alter settings profile to rename, target available", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename("1.0")]):
|
||||
with When("I alter settings profile by renaming it"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 RENAME TO profile0")
|
||||
|
||||
with Scenario("I alter settings profile to rename, target unavailable", flags=TE, requirements=[RQ_SRS_006_RBAC_SettingsProfile_Alter_Rename("1.0")]):
|
||||
new_profile = "profile1"
|
||||
|
||||
try:
|
||||
with Given(f"Ensure target name {new_profile} is NOT available"):
|
||||
node.query(f"CREATE SETTINGS PROFILE IF NOT EXISTS {new_profile}")
|
||||
|
||||
with When(f"I try to rename to {new_profile}"):
|
||||
exitcode, message = errors.cannot_rename_settings_profile(name="profile0", name_new=new_profile)
|
||||
node.query(f"ALTER SETTINGS PROFILE profile0 RENAME TO {new_profile}", exitcode=exitcode, message=message)
|
||||
finally:
|
||||
with Finally(f"I cleanup target name {new_profile}"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {new_profile}")
|
||||
|
||||
del new_profile
|
||||
|
||||
with Scenario("I alter settings profile with a setting value", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables("1.0"),
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value("1.0")]):
|
||||
with When("I alter settings profile using settings"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage = 100000001")
|
||||
|
||||
with Scenario("I alter settings profile with a setting value, does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables("1.0"),
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value("1.0")]):
|
||||
with When("I alter settings profile using settings and nonexistent value"):
|
||||
exitcode, message = errors.unknown_setting("fake_setting")
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I alter settings profile with a min setting value", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]):
|
||||
with When("I alter settings profile using 2 minimum formats"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MIN 100000001")
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MIN = 100000001")
|
||||
|
||||
with Scenario("I alter settings profile with a max setting value", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]):
|
||||
with When("I alter settings profile using 2 maximum formats"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MAX 100000001")
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MAX = 100000001")
|
||||
|
||||
with Scenario("I alter settings profile with min and max setting values", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]):
|
||||
with When("I alter settings profile with both min and max"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage MIN 100000001 MAX 200000001")
|
||||
|
||||
with Scenario("I alter settings profile with a readonly setting", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]):
|
||||
with When("I alter settings profile with with readonly"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage READONLY")
|
||||
|
||||
with Scenario("I alter settings profile with a writable setting", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Constraints("1.0")]):
|
||||
with When("I alter settings profile with writable"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS max_memory_usage WRITABLE")
|
||||
|
||||
with Scenario("I alter settings profile with inherited settings", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_Inherit("1.0")]):
|
||||
with When("I alter settings profile with inherit"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 SETTINGS INHERIT 'default'")
|
||||
|
||||
with Scenario("I alter settings profile with inherit, parent profile does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_Inherit("1.0")]):
|
||||
profile = "profile3"
|
||||
with Given(f"I ensure that profile {profile} does not exist"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
with When("I alter settings profile inherit from nonexistant parent"):
|
||||
exitcode, message = errors.settings_profile_not_found_in_disk(profile)
|
||||
node.query(f"ALTER PROFILE profile0 SETTINGS INHERIT {profile}", exitcode=exitcode, message=message)
|
||||
del profile
|
||||
|
||||
with Scenario("I alter settings profile with multiple settings", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables("1.0"),
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value("1.0")]):
|
||||
with When("I alter settings profile with multiple settings"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0"
|
||||
" SETTINGS max_memory_usage = 100000001"
|
||||
" SETTINGS max_memory_usage_for_user = 100000001")
|
||||
|
||||
with Scenario("I alter settings profile with multiple settings short form", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables("1.0"),
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Variables_Value("1.0")]):
|
||||
with When("I alter settings profile with short form multiple settings"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0"
|
||||
" SETTINGS max_memory_usage = 100000001,"
|
||||
" max_memory_usage_for_user = 100000001")
|
||||
|
||||
with Scenario("I alter settings profile assigned to one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment("1.0")]):
|
||||
with When("I alter settings profile with assignment to role"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 TO role0")
|
||||
|
||||
with Scenario("I alter settings profile to assign to role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment("1.0")]):
|
||||
role = "role1"
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I alter a settings profile, assign to role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"ALTER SETTINGS PROFILE profile0 TO {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter settings profile to assign to all except role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment("1.0")]):
|
||||
role = "role1"
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I alter a settings profile, assign to all except role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"ALTER SETTINGS PROFILE profile0 TO ALL EXCEPT {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter settings profile assigned to multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment("1.0")]):
|
||||
with When("I alter settings profile with assignment to multiple roles"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 TO role0, user0")
|
||||
|
||||
with Scenario("I alter settings profile assigned to all", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_All("1.0")]):
|
||||
with When("I alter settings profile with assignment to all"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 TO ALL")
|
||||
|
||||
with Scenario("I alter settings profile assigned to all except one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_AllExcept("1.0")]):
|
||||
with When("I alter settings profile with assignment to all except a role"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 TO ALL EXCEPT role0")
|
||||
|
||||
with Scenario("I alter settings profile assigned to all except multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_AllExcept("1.0")]):
|
||||
with When("I alter settings profile with assignmentto all except multiple roles"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 TO ALL EXCEPT role0, user0")
|
||||
|
||||
with Scenario("I alter settings profile assigned to none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_None("1.0")]):
|
||||
with When("I alter settings profile with assignment to none"):
|
||||
node.query("ALTER SETTINGS PROFILE profile0 TO NONE")
|
||||
|
||||
with Scenario("I alter settings profile on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_OnCluster("1.0")]):
|
||||
try:
|
||||
with Given("I have a settings profile on cluster"):
|
||||
node.query("CREATE SETTINGS PROFILE profile1 ON CLUSTER sharded_cluster")
|
||||
with When("I run alter settings profile command"):
|
||||
node.query("ALTER SETTINGS PROFILE profile1 ON CLUSTER sharded_cluster")
|
||||
with And("I alter settings profile with settings"):
|
||||
node.query("ALTER SETTINGS PROFILE profile1 ON CLUSTER sharded_cluster SETTINGS max_memory_usage = 100000001")
|
||||
with And("I alter settings profile with inherit"):
|
||||
node.query("ALTER SETTINGS PROFILE profile1 ON CLUSTER sharded_cluster SETTINGS INHERIT 'default'")
|
||||
with And("I alter settings profile to all"):
|
||||
node.query("ALTER SETTINGS PROFILE profile1 ON CLUSTER sharded_cluster TO ALL")
|
||||
finally:
|
||||
with Finally("I drop the settings profile"):
|
||||
node.query("DROP SETTINGS PROFILE IF EXISTS profile1 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I alter settings profile on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Alter_Assignment_OnCluster("1.0")]):
|
||||
with When("I run alter settings profile command"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("ALTER SETTINGS PROFILE profile1 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
||||
|
||||
finally:
|
||||
with Finally("I drop the profile and all the users and roles"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS profile0")
|
||||
node.query(f"DROP USER IF EXISTS user0")
|
||||
node.query(f"DROP ROLE IF EXISTS role0")
|
324
tests/testflows/rbac/tests/syntax/alter_user.py
Executable file
324
tests/testflows/rbac/tests/syntax/alter_user.py
Executable file
@ -0,0 +1,324 @@
|
||||
import hashlib
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("alter user")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check alter user query syntax.
|
||||
|
||||
```sql
|
||||
ALTER USER [IF EXISTS] name [ON CLUSTER cluster_name]
|
||||
[RENAME TO new_name]
|
||||
[IDENTIFIED [WITH {PLAINTEXT_PASSWORD|SHA256_PASSWORD|DOUBLE_SHA1_PASSWORD}] BY {'password'|'hash'}]
|
||||
[[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
||||
[DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
|
||||
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(user):
|
||||
try:
|
||||
with Given("I have a user"):
|
||||
node.query(f"CREATE USER OR REPLACE {user}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the user", flags=TE):
|
||||
node.query(f"DROP USER IF EXISTS {user}")
|
||||
|
||||
with Scenario("I alter user, base command", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter("1.0")]):
|
||||
with setup("user0"):
|
||||
with When("I alter user"):
|
||||
node.query("ALTER USER user0")
|
||||
|
||||
with Scenario("I alter user that does not exist without if exists, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter("1.0")]):
|
||||
with When("I run alter user command, expecting error 192"):
|
||||
exitcode, message = errors.user_not_found_in_disk(name="user0")
|
||||
node.query(f"ALTER USER user0",exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I alter user with if exists", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_IfExists("1.0")]):
|
||||
with setup("user0"):
|
||||
with When(f"I alter user with if exists"):
|
||||
node.query(f"ALTER USER IF EXISTS user0")
|
||||
|
||||
with Scenario("I alter user that does not exist with if exists", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_IfExists("1.0")]):
|
||||
user = "user0"
|
||||
with Given("I don't have a user"):
|
||||
node.query(f"DROP USER IF EXISTS {user}")
|
||||
with When(f"I alter user {user} with if exists"):
|
||||
node.query(f"ALTER USER IF EXISTS {user}")
|
||||
del user
|
||||
|
||||
with Scenario("I alter user on a cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Cluster("1.0")]):
|
||||
with Given("I have a user on a cluster"):
|
||||
node.query("CREATE USER OR REPLACE user0 ON CLUSTER sharded_cluster")
|
||||
with When("I alter user on a cluster"):
|
||||
node.query("ALTER USER user0 ON CLUSTER sharded_cluster")
|
||||
with Finally("I drop user from cluster"):
|
||||
node.query("DROP USER IF EXISTS user0 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I alter user on a fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Cluster("1.0")]):
|
||||
with When("I alter user on a fake cluster"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("ALTER USER user0 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I alter user to rename, target available", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Rename("1.0")]):
|
||||
with setup("user15"):
|
||||
with When("I alter user name"):
|
||||
node.query("ALTER USER user15 RENAME TO user15")
|
||||
|
||||
with Scenario("I alter user to rename, target unavailable", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Rename("1.0")]):
|
||||
with setup("user15"):
|
||||
new_user = "user16"
|
||||
try:
|
||||
with Given(f"Ensure target name {new_user} is NOT available"):
|
||||
node.query(f"CREATE USER IF NOT EXISTS {new_user}")
|
||||
with When(f"I try to rename to {new_user}"):
|
||||
exitcode, message = errors.cannot_rename_user(name="user15", name_new=new_user)
|
||||
node.query(f"ALTER USER user15 RENAME TO {new_user}", exitcode=exitcode, message=message)
|
||||
finally:
|
||||
with Finally(f"I cleanup target name {new_user}"):
|
||||
node.query(f"DROP USER IF EXISTS {new_user}")
|
||||
del new_user
|
||||
|
||||
with Scenario("I alter user password plaintext password", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Password_PlainText("1.0")]):
|
||||
with setup("user1"):
|
||||
with When("I alter user with plaintext password"):
|
||||
node.query("ALTER USER user1 IDENTIFIED WITH PLAINTEXT_PASSWORD BY 'mypassword'", step=When)
|
||||
|
||||
with Scenario("I alter user password to sha256", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Password_Sha256Password("1.0")]):
|
||||
with setup("user2"):
|
||||
with When("I alter user with sha256_password"):
|
||||
password = hashlib.sha256("mypassword".encode("utf-8")).hexdigest()
|
||||
node.query(f"ALTER USER user2 IDENTIFIED WITH SHA256_PASSWORD BY '{password}'",step=When)
|
||||
|
||||
with Scenario("I alter user password to double_sha1_password", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Password_DoubleSha1Password("1.0")]):
|
||||
with setup("user3"):
|
||||
with When("I alter user with double_sha1_password"):
|
||||
def hash(password):
|
||||
return hashlib.sha1(password.encode("utf-8")).hexdigest()
|
||||
password = hash(hash("mypassword"))
|
||||
node.query(f"ALTER USER user3 IDENTIFIED WITH DOUBLE_SHA1_PASSWORD BY '{password}'", step=When)
|
||||
|
||||
with Scenario("I alter user host local", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_Local("1.0")]):
|
||||
with setup("user4"):
|
||||
with When("I alter user with host local"):
|
||||
node.query("ALTER USER user4 HOST LOCAL")
|
||||
|
||||
with Scenario("I alter user host name", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_Name("1.0")]):
|
||||
with setup("user5"):
|
||||
with When("I alter user with host name"):
|
||||
node.query("ALTER USER user5 HOST NAME 'localhost', NAME 'clickhouse.com'")
|
||||
|
||||
with Scenario("I alter user host regexp", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_Regexp("1.0")]):
|
||||
with setup("user6"):
|
||||
with When("I alter user with host regexp"):
|
||||
node.query("ALTER USER user6 HOST REGEXP 'lo..*host', 'lo*host'")
|
||||
|
||||
with Scenario("I alter user host ip", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_IP("1.0")]):
|
||||
with setup("user7"):
|
||||
with When("I alter user with host ip"):
|
||||
node.query("ALTER USER user7 HOST IP '127.0.0.1', IP '127.0.0.2'")
|
||||
|
||||
with Scenario("I alter user host like", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_Like("1.0")]):
|
||||
with setup("user8"):
|
||||
with When("I alter user with host like"):
|
||||
node.query("ALTER USER user8 HOST LIKE '%.clickhouse.com'")
|
||||
|
||||
with Scenario("I alter user host any", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_Any("1.0")]):
|
||||
with setup("user9"):
|
||||
with When("I alter user with host any"):
|
||||
node.query("ALTER USER user9 HOST ANY")
|
||||
|
||||
with Scenario("I alter user host many hosts", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_Like("1.0")]):
|
||||
with setup("user11"):
|
||||
with When("I alter user with multiple hosts"):
|
||||
node.query("ALTER USER user11 HOST LIKE '%.clickhouse.com', \
|
||||
IP '127.0.0.2', NAME 'localhost', REGEXP 'lo*host'")
|
||||
|
||||
with Scenario("I alter user default role set to none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_None("1.0")]):
|
||||
with setup("user12"):
|
||||
with When("I alter user with default role none"):
|
||||
node.query("ALTER USER user12 DEFAULT ROLE NONE")
|
||||
|
||||
with Scenario("I alter user default role set to all", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_DefaultRole_All("1.0")]):
|
||||
with setup("user13"):
|
||||
with When("I alter user with all roles set to default"):
|
||||
node.query("ALTER USER user13 DEFAULT ROLE ALL")
|
||||
|
||||
@contextmanager
|
||||
def setup_role(role):
|
||||
try:
|
||||
with Given(f"I have a role {role}"):
|
||||
node.query(f"CREATE ROLE OR REPLACE {role}")
|
||||
yield
|
||||
finally:
|
||||
with Finally(f"I drop the role {role}", flags=TE):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
|
||||
with Scenario("I alter user default role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]):
|
||||
with setup("user14"), setup_role("role2"):
|
||||
with Given("I have a user with a role"):
|
||||
node.query("GRANT role2 TO user14")
|
||||
with When("I alter user default role"):
|
||||
node.query("ALTER USER user14 DEFAULT ROLE role2")
|
||||
|
||||
with Scenario("I alter user default role, setting default role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]):
|
||||
with setup("user14a"), setup_role("default"):
|
||||
with Given("I grant default role to the user"):
|
||||
node.query("GRANT default TO user14a")
|
||||
with When("I alter user default role"):
|
||||
node.query("ALTER USER user14a DEFAULT ROLE default")
|
||||
|
||||
with Scenario("I alter user default role, role doesn't exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]):
|
||||
with setup("user12"):
|
||||
role = "role0"
|
||||
with Given(f"I ensure that role {role} does not exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with When(f"I alter user with default role {role}"):
|
||||
exitcode, message = errors.role_not_found_in_disk(role)
|
||||
node.query(f"ALTER USER user12 DEFAULT ROLE {role}",exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter user default role, all except role doesn't exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]):
|
||||
with setup("user12"):
|
||||
role = "role0"
|
||||
with Given(f"I ensure that role {role} does not exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with When(f"I alter user with default role {role}"):
|
||||
exitcode, message = errors.role_not_found_in_disk(role)
|
||||
node.query(f"ALTER USER user12 DEFAULT ROLE ALL EXCEPT {role}",exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I alter user default role multiple", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_DefaultRole("1.0")]):
|
||||
with setup("user15"), setup_role("second"), setup_role("third"):
|
||||
with Given("I have a user with multiple roles"):
|
||||
node.query("GRANT second,third TO user15")
|
||||
with When("I alter user default role to second, third"):
|
||||
node.query("ALTER USER user15 DEFAULT ROLE second, third")
|
||||
|
||||
with Scenario("I alter user default role set to all except", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_DefaultRole_AllExcept("1.0")]):
|
||||
with setup("user16"), setup_role("second"):
|
||||
with Given("I have a user with a role"):
|
||||
node.query("GRANT second TO user16")
|
||||
with When("I alter user default role"):
|
||||
node.query("ALTER USER user16 DEFAULT ROLE ALL EXCEPT second")
|
||||
|
||||
with Scenario("I alter user default role multiple all except", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_DefaultRole_AllExcept("1.0")]):
|
||||
with setup("user17"), setup_role("second"), setup_role("third"):
|
||||
with Given("I have a user with multiple roles"):
|
||||
node.query("GRANT second,third TO user17")
|
||||
with When("I alter user default role to all except second"):
|
||||
node.query("ALTER USER user17 DEFAULT ROLE ALL EXCEPT second")
|
||||
|
||||
with Scenario("I alter user settings profile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings("1.0"), \
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings_Profile("1.0")]):
|
||||
with setup("user18"):
|
||||
try:
|
||||
with Given("I have a profile"):
|
||||
node.query(f"CREATE SETTINGS PROFILE profile10")
|
||||
with When("I alter user with settings and set profile to profile1"):
|
||||
node.query("ALTER USER user18 SETTINGS PROFILE profile10, max_memory_usage = 100 MIN 0 MAX 1000 READONLY")
|
||||
finally:
|
||||
with Finally("I drop the profile"):
|
||||
node.query(f"DROP SETTINGS PROFILE profile10")
|
||||
|
||||
with Scenario("I alter user settings profile, fake profile, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings("1.0"),
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings_Profile("1.0")]):
|
||||
with setup("user18a"):
|
||||
profile = "profile0"
|
||||
with Given(f"I ensure that profile {profile} does not exist"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
with When(f"I alter user with Settings and set profile to fake profile {profile}"):
|
||||
exitcode, message = errors.settings_profile_not_found_in_disk(profile)
|
||||
node.query("ALTER USER user18a SETTINGS PROFILE profile0", exitcode=exitcode, message=message)
|
||||
del profile
|
||||
|
||||
with Scenario("I alter user settings with a fake setting, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings("1.0")]):
|
||||
with setup("user18b"):
|
||||
with When("I alter settings profile using settings and nonexistent value"):
|
||||
exitcode, message = errors.unknown_setting("fake_setting")
|
||||
node.query("ALTER USER user18b SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I alter user settings without profile (no equals)", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings("1.0"),
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings_Min("1.0"),
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings_Max("1.0")]):
|
||||
with setup("user19"):
|
||||
with When("I alter user with settings without profile using no equals"):
|
||||
node.query("ALTER USER user19 SETTINGS max_memory_usage=10000000 MIN 100000 MAX 1000000000 READONLY")
|
||||
|
||||
#equals sign (=) syntax verify
|
||||
with Scenario("I alter user settings without profile (yes equals)", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings("1.0"),
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings_Min("1.0"),
|
||||
RQ_SRS_006_RBAC_User_Alter_Settings_Max("1.0")]):
|
||||
with setup("user20"):
|
||||
with When("I alter user with settings without profile using equals"):
|
||||
node.query("ALTER USER user20 SETTINGS max_memory_usage=10000000 MIN=100000 MAX=1000000000 READONLY")
|
||||
|
||||
#Add requirement to host: add/drop
|
||||
with Scenario("I alter user to add host", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_AddDrop("1.0")]):
|
||||
with setup("user21"):
|
||||
with When("I alter user by adding local host"):
|
||||
node.query("ALTER USER user21 ADD HOST LOCAL")
|
||||
with And("I alter user by adding no host"):
|
||||
node.query("ALTER USER user21 ADD HOST NONE")
|
||||
with And("I alter user by adding host like"):
|
||||
node.query("ALTER USER user21 ADD HOST LIKE 'local%'")
|
||||
with And("I alter user by adding host ip"):
|
||||
node.query("ALTER USER user21 ADD HOST IP '127.0.0.1'")
|
||||
with And("I alter user by adding host name"):
|
||||
node.query("ALTER USER user21 ADD HOST NAME 'localhost'")
|
||||
|
||||
with Scenario("I alter user to remove host", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Alter_Host_AddDrop("1.0")]):
|
||||
with setup("user22"):
|
||||
with When("I alter user by removing local host"):
|
||||
node.query("ALTER USER user22 DROP HOST LOCAL")
|
||||
with And("I alter user by removing no host"):
|
||||
node.query("ALTER USER user22 DROP HOST NONE")
|
||||
with And("I alter user by removing like host"):
|
||||
node.query("ALTER USER user22 DROP HOST LIKE 'local%'")
|
||||
with And("I alter user by removing host ip"):
|
||||
node.query("ALTER USER user22 DROP HOST IP '127.0.0.1'")
|
||||
with And("I alter user by removing host name"):
|
||||
node.query("ALTER USER user22 DROP HOST NAME 'localhost'")
|
227
tests/testflows/rbac/tests/syntax/create_quota.py
Executable file
227
tests/testflows/rbac/tests/syntax/create_quota.py
Executable file
@ -0,0 +1,227 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("create quota")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check create quota query syntax.
|
||||
|
||||
```sql
|
||||
CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name]
|
||||
[KEYED BY {'none' | 'user name' | 'ip address' | 'client key' | 'client key or user name' | 'client key or ip address'}]
|
||||
[FOR [RANDOMIZED] INTERVAL number {SECOND | MINUTE | HOUR | DAY}
|
||||
{MAX { {QUERIES | ERRORS | RESULT ROWS | RESULT BYTES | READ ROWS | READ BYTES | EXECUTION TIME} = number } [,...] |
|
||||
NO LIMITS | TRACKING ONLY} [,...]]
|
||||
[TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(quota):
|
||||
try:
|
||||
with Given("I ensure the quota does not already exist"):
|
||||
node.query(f"DROP QUOTA IF EXISTS {quota}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the quota"):
|
||||
node.query(f"DROP QUOTA IF EXISTS {quota}")
|
||||
|
||||
def create_quota(quota):
|
||||
with And(f"I ensure I do have quota {quota}"):
|
||||
node.query(f"CREATE QUOTA OR REPLACE {quota}")
|
||||
|
||||
try:
|
||||
with Given("I have a user and a role"):
|
||||
node.query(f"CREATE USER user0")
|
||||
node.query(f"CREATE ROLE role0")
|
||||
|
||||
with Scenario("I create quota with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create("1.0")]):
|
||||
with cleanup("quota0"):
|
||||
with When("I create a quota with no options"):
|
||||
node.query("CREATE QUOTA quota0")
|
||||
|
||||
with Scenario("I create quota that already exists, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create("1.0")]):
|
||||
quota = "quota0"
|
||||
with cleanup(quota):
|
||||
create_quota(quota)
|
||||
with When(f"I create a quota {quota} that already exists without IF EXISTS, throws exception"):
|
||||
exitcode, message = errors.cannot_insert_quota(name=quota)
|
||||
node.query(f"CREATE QUOTA {quota}", exitcode=exitcode, message=message)
|
||||
del quota
|
||||
|
||||
with Scenario("I create quota if not exists, quota does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_IfNotExists("1.0")]):
|
||||
quota = "quota1"
|
||||
with cleanup(quota):
|
||||
with When(f"I create a quota {quota} with if not exists"):
|
||||
node.query(f"CREATE QUOTA IF NOT EXISTS {quota}")
|
||||
del quota
|
||||
|
||||
with Scenario("I create quota if not exists, quota does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_IfNotExists("1.0")]):
|
||||
quota = "quota1"
|
||||
with cleanup(quota):
|
||||
create_quota(quota)
|
||||
with When(f"I create a quota {quota} with if not exists"):
|
||||
node.query(f"CREATE QUOTA IF NOT EXISTS {quota}")
|
||||
del quota
|
||||
|
||||
with Scenario("I create quota or replace, quota does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Replace("1.0")]):
|
||||
quota = "quota2"
|
||||
with cleanup(quota):
|
||||
with When(f"I create a quota {quota} with or replace"):
|
||||
node.query(f"CREATE QUOTA OR REPLACE {quota}")
|
||||
del quota
|
||||
|
||||
with Scenario("I create quota or replace, quota does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Replace("1.0")]):
|
||||
quota = "quota2"
|
||||
with cleanup(quota):
|
||||
create_quota(quota)
|
||||
with When(f"I create a quota {quota} with or replace"):
|
||||
node.query(f"CREATE QUOTA OR REPLACE {quota}")
|
||||
del quota
|
||||
|
||||
keys = ['none', 'user name', 'ip address', 'client key', 'client key or user name', 'client key or ip address']
|
||||
for i, key in enumerate(keys):
|
||||
with Scenario(f"I create quota keyed by {key}", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_KeyedBy("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_KeyedByOptions("1.0")]):
|
||||
name = f'quota{3 + i}'
|
||||
with cleanup(name):
|
||||
with When(f"I create a quota with {key}"):
|
||||
node.query(f"CREATE QUOTA {name} KEYED BY '{key}'")
|
||||
|
||||
with Scenario("I create quota for randomized interval", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Interval_Randomized("1.0")]):
|
||||
with cleanup("quota9"):
|
||||
with When("I create a quota for randomized interval"):
|
||||
node.query("CREATE QUOTA quota9 FOR RANDOMIZED INTERVAL 1 DAY NO LIMITS")
|
||||
|
||||
intervals = ['SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH']
|
||||
for i, interval in enumerate(intervals):
|
||||
with Scenario(f"I create quota for interval {interval}", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Interval("1.0")]):
|
||||
name = f'quota{10 + i}'
|
||||
with cleanup(name):
|
||||
with When(f"I create a quota for {interval} interval"):
|
||||
node.query(f"CREATE QUOTA {name} FOR INTERVAL 1 {interval} NO LIMITS")
|
||||
|
||||
constraints = ['MAX QUERIES', 'MAX ERRORS', 'MAX RESULT ROWS',
|
||||
'MAX RESULT BYTES', 'MAX READ ROWS', 'MAX READ BYTES', 'MAX EXECUTION TIME',
|
||||
'NO LIMITS', 'TRACKING ONLY']
|
||||
for i, constraint in enumerate(constraints):
|
||||
with Scenario(f"I create quota for {constraint.lower()}", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Queries("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_Errors("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_ResultRows("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_ResultBytes("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_ReadRows("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_ReadBytes("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_ExecutionTime("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_NoLimits("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_TrackingOnly("1.0")]):
|
||||
name = f'quota{15 + i}'
|
||||
with cleanup(name):
|
||||
with When(f"I create quota for {constraint.lower()}"):
|
||||
node.query(f"CREATE QUOTA {name} FOR INTERVAL 1 DAY {constraint}{' 1024' if constraint.startswith('MAX') else ''}")
|
||||
|
||||
with Scenario("I create quota for multiple constraints", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Interval("1.0"),
|
||||
RQ_SRS_006_RBAC_Quota_Create_Queries("1.0")]):
|
||||
with cleanup("quota23"):
|
||||
with When(f"I create quota for multiple constraints"):
|
||||
node.query('CREATE QUOTA quota23 \
|
||||
FOR INTERVAL 1 DAY NO LIMITS, \
|
||||
FOR INTERVAL 2 DAY MAX QUERIES 124, \
|
||||
FOR INTERVAL 1 HOUR TRACKING ONLY')
|
||||
|
||||
with Scenario("I create quota assigned to one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Assignment("1.0")]):
|
||||
with cleanup("quota24"):
|
||||
with When("I create quota for role"):
|
||||
node.query("CREATE QUOTA quota24 TO role0")
|
||||
|
||||
with Scenario("I create quota to assign to role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Assignment("1.0")]):
|
||||
role = "role1"
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I create a quota, assign to role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"CREATE QUOTA quota0 TO {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create quota to assign to all except role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Assignment("1.0")]):
|
||||
role = "role1"
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I create a quota, assign to all except role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"CREATE QUOTA quota0 TO ALL EXCEPT {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create quota assigned to no role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Assignment_None("1.0")]):
|
||||
with When("I create quota for no role"):
|
||||
node.query("CREATE QUOTA quota24 TO NONE")
|
||||
|
||||
with Scenario("I create quota assigned to multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Assignment("1.0")]):
|
||||
with cleanup("quota25"):
|
||||
with When("I create quota for multiple roles"):
|
||||
node.query("CREATE QUOTA quota25 TO role0, user0")
|
||||
|
||||
with Scenario("I create quota assigned to all", flags=TE,requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Assignment_All("1.0")]):
|
||||
with cleanup("quota26"):
|
||||
with When("I create quota for all"):
|
||||
node.query("CREATE QUOTA quota26 TO ALL")
|
||||
|
||||
with Scenario("I create quota assigned to all except one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Assignment_Except("1.0")]):
|
||||
with cleanup("quota27"):
|
||||
with When("I create quota for all except one role"):
|
||||
node.query("CREATE QUOTA quota27 TO ALL EXCEPT role0")
|
||||
|
||||
with Scenario("I create quota assigned to all except multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Assignment_Except("1.0")]):
|
||||
with cleanup("quota28"):
|
||||
with When("I create quota for all except multiple roles"):
|
||||
node.query("CREATE QUOTA quota28 TO ALL EXCEPT role0, user0")
|
||||
|
||||
with Scenario("I create quota on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Cluster("1.0")]):
|
||||
try:
|
||||
with When("I run create quota command on cluster"):
|
||||
node.query("CREATE QUOTA quota29 ON CLUSTER sharded_cluster")
|
||||
with When("I run create quota command on cluster, keyed"):
|
||||
node.query("CREATE QUOTA OR REPLACE quota29 ON CLUSTER sharded_cluster KEYED BY 'none'")
|
||||
with When("I run create quota command on cluster, interval"):
|
||||
node.query("CREATE QUOTA OR REPLACE quota29 ON CLUSTER sharded_cluster FOR INTERVAL 1 DAY TRACKING ONLY")
|
||||
with When("I run create quota command on cluster, assign"):
|
||||
node.query("CREATE QUOTA OR REPLACE quota29 ON CLUSTER sharded_cluster TO ALL")
|
||||
finally:
|
||||
with Finally("I drop the quota from cluster"):
|
||||
node.query("DROP QUOTA IF EXISTS quota29 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I create quota on nonexistent cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Create_Cluster("1.0")]):
|
||||
with When("I run create quota on a cluster"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("CREATE QUOTA quota0 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
||||
|
||||
finally:
|
||||
with Finally("I drop all the users and roles"):
|
||||
node.query(f"DROP USER IF EXISTS user0")
|
||||
node.query(f"DROP ROLE IF EXISTS role0")
|
122
tests/testflows/rbac/tests/syntax/create_role.py
Executable file
122
tests/testflows/rbac/tests/syntax/create_role.py
Executable file
@ -0,0 +1,122 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("create role")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check create role query syntax.
|
||||
|
||||
```sql
|
||||
CREATE ROLE [IF NOT EXISTS | OR REPLACE] name
|
||||
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(role):
|
||||
try:
|
||||
with Given("I ensure the role doesn't already exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the role"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
|
||||
def create_role(role):
|
||||
with Given(f"I ensure I do have role {role}"):
|
||||
node.query(f"CREATE ROLE OR REPLACE {role}")
|
||||
|
||||
with Scenario("I create role with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create("1.0")]):
|
||||
with cleanup("role0"):
|
||||
with When("I create role"):
|
||||
node.query("CREATE ROLE role0")
|
||||
|
||||
with Scenario("I create role that already exists, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create("1.0")]):
|
||||
role = "role0"
|
||||
with cleanup(role):
|
||||
with When(f"I create role {role}"):
|
||||
exitcode, message = errors.cannot_insert_role(name=role)
|
||||
node.query(f"CREATE ROLE {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create role if not exists, role does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create_IfNotExists("1.0")]):
|
||||
role = "role1"
|
||||
with cleanup(role):
|
||||
with When(f"I create role {role} with if not exists"):
|
||||
node.query(f"CREATE ROLE IF NOT EXISTS {role}")
|
||||
del role
|
||||
|
||||
with Scenario("I create role if not exists, role does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create_IfNotExists("1.0")]):
|
||||
role = "role1"
|
||||
with cleanup(role):
|
||||
create_role(role)
|
||||
with When(f"I create role {role} with if not exists"):
|
||||
node.query(f"CREATE ROLE IF NOT EXISTS {role}")
|
||||
del role
|
||||
|
||||
with Scenario("I create role or replace, role does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create_Replace("1.0")]):
|
||||
role = "role2"
|
||||
with cleanup(role):
|
||||
with When(f"I create role {role} with or replace"):
|
||||
node.query(f"CREATE ROLE OR REPLACE {role}")
|
||||
del role
|
||||
|
||||
with Scenario("I create role or replace, role does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create_Replace("1.0")]):
|
||||
role = "role2"
|
||||
with cleanup(role):
|
||||
create_role(role)
|
||||
with When(f"I create role {role} with or replace"):
|
||||
node.query(f"CREATE ROLE OR REPLACE {role}")
|
||||
del role
|
||||
|
||||
with Scenario("I create role on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create("1.0")]):
|
||||
try:
|
||||
with When("I have a role on a cluster"):
|
||||
node.query("CREATE ROLE role1 ON CLUSTER sharded_cluster")
|
||||
with And("I run create role or replace on a cluster"):
|
||||
node.query("CREATE ROLE OR REPLACE role1 ON CLUSTER sharded_cluster")
|
||||
with And("I create role with settings on a cluster"):
|
||||
node.query("CREATE ROLE role2 ON CLUSTER sharded_cluster SETTINGS max_memory_usage=10000000 READONLY")
|
||||
finally:
|
||||
with Finally("I drop the role"):
|
||||
node.query("DROP ROLE IF EXISTS role1,role2 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I create role on nonexistent cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create("1.0")]):
|
||||
with When("I run create role on a cluster"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("CREATE ROLE role1 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I create role with settings profile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create_Settings("1.0")]):
|
||||
with cleanup("role3"):
|
||||
with When("I create role with settings profile"):
|
||||
node.query("CREATE ROLE role3 SETTINGS PROFILE default, max_memory_usage=10000000 WRITABLE")
|
||||
|
||||
with Scenario("I create role settings profile, fake profile, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create_Settings("1.0")]):
|
||||
with cleanup("role4a"):
|
||||
with Given("I ensure profile profile0 does not exist"):
|
||||
node.query("DROP SETTINGS PROFILE IF EXISTS profile0")
|
||||
with When("I create role with settings profile that does not exist"):
|
||||
exitcode, message = errors.settings_profile_not_found_in_disk("profile0")
|
||||
node.query("CREATE ROLE role4a SETTINGS PROFILE profile0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I create role with settings without profile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Create_Settings("1.0")]):
|
||||
with cleanup("role4"):
|
||||
with When("I create role with settings without profile"):
|
||||
node.query("CREATE ROLE role4 SETTINGS max_memory_usage=10000000 READONLY")
|
225
tests/testflows/rbac/tests/syntax/create_row_policy.py
Executable file
225
tests/testflows/rbac/tests/syntax/create_row_policy.py
Executable file
@ -0,0 +1,225 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("create row policy")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check create row policy query syntax.
|
||||
|
||||
```sql
|
||||
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name [ON CLUSTER cluster_name] ON [db.]table
|
||||
[AS {PERMISSIVE | RESTRICTIVE}]
|
||||
[FOR SELECT]
|
||||
[USING condition]
|
||||
[TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(policy, on="default.foo"):
|
||||
try:
|
||||
with Given(f"I ensure the row policy does not already exist on {on}"):
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {policy} ON {on}")
|
||||
yield
|
||||
finally:
|
||||
with Finally(f"I drop the row policy on {on}"):
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {policy} ON {on}")
|
||||
|
||||
def create_policy(policy, on="default.foo"):
|
||||
with Given(f"I ensure I do have policy {policy} on {on}"):
|
||||
node.query(f"CREATE ROW POLICY OR REPLACE {policy} ON {on}")
|
||||
|
||||
try:
|
||||
with Given("I have a table and some roles"):
|
||||
node.query(f"CREATE TABLE default.foo (x UInt64, y String) Engine=Memory")
|
||||
node.query(f"CREATE ROLE role0")
|
||||
node.query(f"CREATE ROLE role1")
|
||||
|
||||
with Scenario("I create row policy with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy0"):
|
||||
with When("I create row policy"):
|
||||
node.query("CREATE ROW POLICY policy0 ON default.foo")
|
||||
|
||||
with Scenario("I create row policy using short syntax with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy1"):
|
||||
with When("I create row policy short form"):
|
||||
node.query("CREATE POLICY policy1 ON default.foo")
|
||||
|
||||
with Scenario("I create row policy that already exists, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
policy = "policy0"
|
||||
with cleanup(policy):
|
||||
create_policy(policy)
|
||||
with When(f"I create row policy {policy}"):
|
||||
exitcode, message = errors.cannot_insert_row_policy(name=f"{policy} ON default.foo")
|
||||
node.query(f"CREATE ROW POLICY {policy} ON default.foo", exitcode=exitcode, message=message)
|
||||
del policy
|
||||
|
||||
with Scenario("I create row policy if not exists, policy does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_IfNotExists("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy2"):
|
||||
with When("I create row policy with if not exists"):
|
||||
node.query("CREATE ROW POLICY IF NOT EXISTS policy2 ON default.foo")
|
||||
|
||||
with Scenario("I create row policy if not exists, policy does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_IfNotExists("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
policy = "policy2"
|
||||
with cleanup(policy):
|
||||
create_policy(policy)
|
||||
with When(f"I create row policy {policy} with if not exists"):
|
||||
node.query(f"CREATE ROW POLICY IF NOT EXISTS {policy} ON default.foo")
|
||||
del policy
|
||||
|
||||
with Scenario("I create row policy or replace, policy does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Replace("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy3"):
|
||||
with When("I create row policy with or replace"):
|
||||
node.query("CREATE ROW POLICY OR REPLACE policy3 ON default.foo")
|
||||
|
||||
with Scenario("I create row policy or replace, policy does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Replace("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
policy = "policy3"
|
||||
with cleanup(policy):
|
||||
create_policy(policy)
|
||||
with When(f"I create row policy {policy} with or replace"):
|
||||
node.query(f"CREATE ROW POLICY OR REPLACE {policy} ON default.foo")
|
||||
del policy
|
||||
|
||||
with Scenario("I create row policy as permissive", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Access_Permissive("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy4"):
|
||||
with When("I create row policy as permissive"):
|
||||
node.query("CREATE ROW POLICY policy4 ON default.foo AS PERMISSIVE")
|
||||
|
||||
with Scenario("I create row policy as restrictive", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Access_Restrictive("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy5"):
|
||||
with When("I create row policy as restrictive"):
|
||||
node.query("CREATE ROW POLICY policy5 ON default.foo AS RESTRICTIVE")
|
||||
|
||||
with Scenario("I create row policy for select", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_ForSelect("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Condition("1.0")]):
|
||||
with cleanup("policy6"):
|
||||
with When("I create row policy with for select"):
|
||||
node.query("CREATE ROW POLICY policy6 ON default.foo FOR SELECT USING x > 10")
|
||||
|
||||
with Scenario("I create row policy using condition", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Condition("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy6"):
|
||||
with When("I create row policy with condition"):
|
||||
node.query("CREATE ROW POLICY policy6 ON default.foo USING x > 10")
|
||||
|
||||
with Scenario("I create row policy assigned to one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy7"):
|
||||
with When("I create row policy for one role"):
|
||||
node.query("CREATE ROW POLICY policy7 ON default.foo TO role0")
|
||||
|
||||
with Scenario("I create row policy to assign to role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0")]):
|
||||
role = "role2"
|
||||
with cleanup("policy8a"):
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I create a row policy, assign to role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"CREATE ROW POLICY policy8a ON default.foo TO {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create row policy to assign to all excpet role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0")]):
|
||||
role = "role2"
|
||||
with cleanup("policy8a"):
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I create a row policy, assign to all except role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"CREATE ROW POLICY policy8a ON default.foo TO ALL EXCEPT {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create row policy assigned to multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Assignment("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy8b"):
|
||||
with When("I create row policy for multiple roles"):
|
||||
node.query("CREATE ROW POLICY policy8b ON default.foo TO role0, role1")
|
||||
|
||||
with Scenario("I create row policy assigned to all", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_All("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy9"):
|
||||
with When("I create row policy for all"):
|
||||
node.query("CREATE ROW POLICY policy9 ON default.foo TO ALL")
|
||||
|
||||
with Scenario("I create row policy assigned to all except one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_AllExcept("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy10"):
|
||||
with When("I create row policy for all except one"):
|
||||
node.query("CREATE ROW POLICY policy10 ON default.foo TO ALL EXCEPT role0")
|
||||
|
||||
with Scenario("I create row policy assigned to all except multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_AllExcept("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy11"):
|
||||
with When("I create row policy for all except multiple roles"):
|
||||
node.query("CREATE ROW POLICY policy11 ON default.foo TO ALL EXCEPT role0, role1")
|
||||
|
||||
with Scenario("I create row policy assigned to none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_Assignment_None("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with cleanup("policy11"):
|
||||
with When("I create row policy for none"):
|
||||
node.query("CREATE ROW POLICY policy11 ON default.foo TO NONE")
|
||||
|
||||
with Scenario("I create row policy on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
try:
|
||||
with When("I run create row policy command on cluster"):
|
||||
node.query("CREATE ROW POLICY policy12 ON CLUSTER sharded_cluster ON default.foo")
|
||||
finally:
|
||||
with Finally("I drop the row policy from cluster"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy12 ON default.foo ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I create row policy on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
with When("I run create row policy command"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("CREATE ROW POLICY policy13 ON CLUSTER fake_cluster ON default.foo", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I create row policy on cluster after table", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Create_On("1.0")]):
|
||||
try:
|
||||
with When("I run create row policy command on cluster"):
|
||||
node.query("CREATE ROW POLICY policy12 ON default.foo ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I drop the row policy from cluster"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy12 ON default.foo ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I drop the table and the roles"):
|
||||
node.query(f"DROP TABLE IF EXISTS default.foo")
|
||||
node.query(f"DROP ROLE IF EXISTS role0, role1")
|
254
tests/testflows/rbac/tests/syntax/create_settings_profile.py
Executable file
254
tests/testflows/rbac/tests/syntax/create_settings_profile.py
Executable file
@ -0,0 +1,254 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("create settings profile")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check create settings profile query syntax.
|
||||
|
||||
```sql
|
||||
CREATE [SETTINGS] PROFILE [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name]
|
||||
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value]
|
||||
[READONLY] | [INHERIT|PROFILE 'profile_name']] [,...]
|
||||
[TO {role [,...] | ALL | ALL EXCEPT role [,...]}]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(profile):
|
||||
try:
|
||||
with Given(f"I ensure the profile {profile} does not exist"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the profile"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
|
||||
def create_profile(profile):
|
||||
with Given(f"I ensure I do have profile {profile}"):
|
||||
node.query(f"CREATE SETTINGS PROFILE OR REPLACE {profile}")
|
||||
|
||||
try:
|
||||
with Given("I have a user and a role"):
|
||||
node.query(f"CREATE USER user0")
|
||||
node.query(f"CREATE ROLE role0")
|
||||
|
||||
with Scenario("I create settings profile with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create("1.0")]):
|
||||
with cleanup("profile0"):
|
||||
with When("I create settings profile"):
|
||||
node.query("CREATE SETTINGS PROFILE profile0")
|
||||
|
||||
with Scenario("I create settings profile that already exists, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create("1.0")]):
|
||||
profile = "profile0"
|
||||
with cleanup(profile):
|
||||
create_profile(profile)
|
||||
with When(f"I create settings profile {profile} that already exists"):
|
||||
exitcode, message = errors.cannot_insert_settings_profile(name=profile)
|
||||
node.query(f"CREATE SETTINGS PROFILE {profile}", exitcode=exitcode, message=message)
|
||||
del profile
|
||||
|
||||
with Scenario("I create settings profile if not exists, profile does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_IfNotExists("1.0")]):
|
||||
with cleanup("profile1"):
|
||||
with When("I create settings profile with if not exists"):
|
||||
node.query("CREATE SETTINGS PROFILE IF NOT EXISTS profile1")
|
||||
|
||||
with Scenario("I create settings profile if not exists, profile does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_IfNotExists("1.0")]):
|
||||
profile = "profile1"
|
||||
with cleanup(profile):
|
||||
create_profile(profile)
|
||||
with When(f"I create settings profile {profile} with if not exists"):
|
||||
node.query(f"CREATE SETTINGS PROFILE IF NOT EXISTS {profile}")
|
||||
del profile
|
||||
|
||||
with Scenario("I create settings profile or replace, profile does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Replace("1.0")]):
|
||||
with cleanup("profile2"):
|
||||
with When("I create settings policy with or replace"):
|
||||
node.query("CREATE SETTINGS PROFILE OR REPLACE profile2")
|
||||
|
||||
with Scenario("I create settings profile or replace, profile does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Replace("1.0")]):
|
||||
with cleanup("profile2"):
|
||||
create_profile("profile2")
|
||||
with When("I create settings policy with or replace"):
|
||||
node.query("CREATE SETTINGS PROFILE OR REPLACE profile2")
|
||||
|
||||
with Scenario("I create settings profile short form", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create("1.0")]):
|
||||
with cleanup("profile3"):
|
||||
with When("I create settings profile short form"):
|
||||
node.query("CREATE PROFILE profile3")
|
||||
|
||||
with Scenario("I create settings profile with a setting value", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables("1.0"),
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Value("1.0")]):
|
||||
with cleanup("profile4"):
|
||||
with When("I create settings profile with settings"):
|
||||
node.query("CREATE SETTINGS PROFILE profile4 SETTINGS max_memory_usage = 100000001")
|
||||
|
||||
with Scenario("I create settings profile with a setting value, does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables("1.0"),
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Value("1.0")]):
|
||||
with When("I create settings profile using settings and nonexistent value"):
|
||||
exitcode, message = errors.unknown_setting("fake_setting")
|
||||
node.query("CREATE SETTINGS PROFILE profile0 SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I create settings profile with a min setting value", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]):
|
||||
with cleanup("profile5"), cleanup("profile6"):
|
||||
with When("I create settings profile with min setting with and without equals"):
|
||||
node.query("CREATE SETTINGS PROFILE profile5 SETTINGS max_memory_usage MIN 100000001")
|
||||
node.query("CREATE SETTINGS PROFILE profile6 SETTINGS max_memory_usage MIN = 100000001")
|
||||
|
||||
with Scenario("I create settings profile with a max setting value", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]):
|
||||
with cleanup("profile7"), cleanup("profile8"):
|
||||
with When("I create settings profile with max setting with and without equals"):
|
||||
node.query("CREATE SETTINGS PROFILE profile7 SETTINGS max_memory_usage MAX 100000001")
|
||||
node.query("CREATE SETTINGS PROFILE profile8 SETTINGS max_memory_usage MAX = 100000001")
|
||||
|
||||
with Scenario("I create settings profile with min and max setting values", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]):
|
||||
with cleanup("profile9"):
|
||||
with When("I create settings profile with min and max setting"):
|
||||
node.query("CREATE SETTINGS PROFILE profile9 SETTINGS max_memory_usage MIN 100000001 MAX 200000001")
|
||||
|
||||
with Scenario("I create settings profile with a readonly setting", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]):
|
||||
with cleanup("profile10"):
|
||||
with When("I create settings profile with readonly"):
|
||||
node.query("CREATE SETTINGS PROFILE profile10 SETTINGS max_memory_usage READONLY")
|
||||
|
||||
with Scenario("I create settings profile with a writable setting", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]):
|
||||
with cleanup("profile21"):
|
||||
with When("I create settings profile with writable"):
|
||||
node.query("CREATE SETTINGS PROFILE profile21 SETTINGS max_memory_usage WRITABLE")
|
||||
|
||||
with Scenario("I create settings profile with inherited settings", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit("1.0")]):
|
||||
with cleanup("profile11"):
|
||||
with When("I create settings profile with inherit"):
|
||||
node.query("CREATE SETTINGS PROFILE profile11 SETTINGS INHERIT 'default'")
|
||||
|
||||
with Scenario("I create settings profile with inherit/from profile, fake profile, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit("1.0")]):
|
||||
profile = "profile3"
|
||||
with Given(f"I ensure that profile {profile} does not exist"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
sources = {"INHERIT","PROFILE"}
|
||||
for source in sources:
|
||||
with When(f"I create settings profile {source} from nonexistant parent"):
|
||||
exitcode, message = errors.settings_profile_not_found_in_disk(profile)
|
||||
node.query(f"CREATE PROFILE profile0 SETTINGS {source} {profile}", exitcode=exitcode, message=message)
|
||||
del profile
|
||||
|
||||
with Scenario("I create settings profile with inherited settings other form", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Inherit("1.0")]):
|
||||
with cleanup("profile12"):
|
||||
with When("I create settings profile with inherit short form"):
|
||||
node.query("CREATE PROFILE profile12 SETTINGS PROFILE 'default'")
|
||||
|
||||
with Scenario("I create settings profile with multiple settings", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]):
|
||||
with cleanup("profile13"):
|
||||
with When("I create settings profile with multiple settings"):
|
||||
node.query("CREATE SETTINGS PROFILE profile13"
|
||||
" SETTINGS max_memory_usage = 100000001"
|
||||
" SETTINGS max_memory_usage_for_user = 100000001")
|
||||
|
||||
with Scenario("I create settings profile with multiple settings short form", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Variables_Constraints("1.0")]):
|
||||
with cleanup("profile14"):
|
||||
with When("I create settings profile with multiple settings short form"):
|
||||
node.query("CREATE SETTINGS PROFILE profile14"
|
||||
" SETTINGS max_memory_usage = 100000001,"
|
||||
" max_memory_usage_for_user = 100000001")
|
||||
|
||||
with Scenario("I create settings profile assigned to one role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment("1.0")]):
|
||||
with cleanup("profile15"):
|
||||
with When("I create settings profile for a role"):
|
||||
node.query("CREATE SETTINGS PROFILE profile15 TO role0")
|
||||
|
||||
with Scenario("I create settings profile to assign to role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment("1.0")]):
|
||||
role = "role1"
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I create a settings profile, assign to role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"CREATE SETTINGS PROFILE profile0 TO {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create settings profile to assign to all except role that does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment("1.0")]):
|
||||
role = "role1"
|
||||
with Given(f"I drop {role} if it exists"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with Then(f"I create a settings profile, assign to all except role {role}, which does not exist"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"CREATE SETTINGS PROFILE profile0 TO ALL EXCEPT {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create settings profile assigned to multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment("1.0")]):
|
||||
with cleanup("profile16"):
|
||||
with When("I create settings profile for multiple roles"):
|
||||
node.query("CREATE SETTINGS PROFILE profile16 TO role0, user0")
|
||||
|
||||
with Scenario("I create settings profile assigned to all", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_All("1.0")]):
|
||||
with cleanup("profile17"):
|
||||
with When("I create settings profile for all"):
|
||||
node.query("CREATE SETTINGS PROFILE profile17 TO ALL")
|
||||
|
||||
with Scenario("I create settings profile assigned to all except one role", flags=TE,requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_AllExcept("1.0")]):
|
||||
with cleanup("profile18"):
|
||||
with When("I create settings profile for all except one role"):
|
||||
node.query("CREATE SETTINGS PROFILE profile18 TO ALL EXCEPT role0")
|
||||
|
||||
with Scenario("I create settings profile assigned to all except multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_AllExcept("1.0")]):
|
||||
with cleanup("profile19"):
|
||||
with When("I create settings profile for all except multiple roles"):
|
||||
node.query("CREATE SETTINGS PROFILE profile19 TO ALL EXCEPT role0, user0")
|
||||
|
||||
with Scenario("I create settings profile assigned to none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_Assignment_None("1.0")]):
|
||||
with cleanup("profile22"):
|
||||
with When("I create settings profile for none"):
|
||||
node.query("CREATE SETTINGS PROFILE profile22 TO NONE")
|
||||
|
||||
with Scenario("I create settings profile on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_OnCluster("1.0")]):
|
||||
try:
|
||||
with When("I run create settings profile command"):
|
||||
node.query("CREATE SETTINGS PROFILE profile20 ON CLUSTER sharded_cluster")
|
||||
node.query("CREATE SETTINGS PROFILE OR REPLACE profile20 ON CLUSTER sharded_cluster SETTINGS max_memory_usage = 100000001")
|
||||
node.query("CREATE SETTINGS PROFILE OR REPLACE profile20 ON CLUSTER sharded_cluster SETTINGS INHERIT 'default'")
|
||||
node.query("CREATE SETTINGS PROFILE OR REPLACE profile20 ON CLUSTER sharded_cluster TO ALL")
|
||||
finally:
|
||||
with Finally("I drop the settings profile"):
|
||||
node.query("DROP SETTINGS PROFILE IF EXISTS profile20 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I create settings profile on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Create_OnCluster("1.0")]):
|
||||
with When("I run create settings profile command"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("CREATE SETTINGS PROFILE profile1 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
||||
finally:
|
||||
with Finally("I drop all the users and roles"):
|
||||
node.query(f"DROP USER IF EXISTS user0")
|
||||
node.query(f"DROP ROLE IF EXISTS role0")
|
271
tests/testflows/rbac/tests/syntax/create_user.py
Executable file
271
tests/testflows/rbac/tests/syntax/create_user.py
Executable file
@ -0,0 +1,271 @@
|
||||
import hashlib
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("create user")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check create user query syntax.
|
||||
|
||||
```sql
|
||||
CREATE USER [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name]
|
||||
[IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH}] BY {'password'|'hash'}]
|
||||
[HOST {LOCAL | NAME 'name' | NAME REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
|
||||
[DEFAULT ROLE role [,...]]
|
||||
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(user):
|
||||
try:
|
||||
with Given("I ensure the user does not already exist", flags=TE):
|
||||
node.query(f"DROP USER IF EXISTS {user}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the user", flags=TE):
|
||||
node.query(f"DROP USER IF EXISTS {user}")
|
||||
|
||||
def create_user(user):
|
||||
with Given(f"I ensure I do have user {user}"):
|
||||
node.query(f"CREATE USER OR REPLACE {user}")
|
||||
|
||||
with Scenario("I create user with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create("1.0"),
|
||||
RQ_SRS_006_RBAC_User_Create_Host_Default("1.0")]):
|
||||
with cleanup("user0"):
|
||||
with When("I create a user with no options"):
|
||||
node.query("CREATE USER user0")
|
||||
|
||||
with Scenario("I create user that already exists, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create("1.0"),
|
||||
RQ_SRS_006_RBAC_User_Create_Host_Default("1.0")]):
|
||||
user = "user0"
|
||||
with cleanup(user):
|
||||
create_user(user)
|
||||
with When(f"I create a user {user} that already exists without IF EXISTS, throws exception"):
|
||||
exitcode, message = errors.cannot_insert_user(name=user)
|
||||
node.query(f"CREATE USER {user}", exitcode=exitcode, message=message)
|
||||
del user
|
||||
|
||||
with Scenario("I create user with if not exists, user does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_IfNotExists("1.0")]):
|
||||
user = "user0"
|
||||
with cleanup(user):
|
||||
with When(f"I create a user {user} with if not exists"):
|
||||
node.query(f"CREATE USER IF NOT EXISTS {user}")
|
||||
del user
|
||||
|
||||
#Bug exists, mark as xfail
|
||||
with Scenario("I create user with if not exists, user does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_IfNotExists("1.0")]):
|
||||
user = "user0"
|
||||
with cleanup(user):
|
||||
create_user(user)
|
||||
with When(f"I create a user {user} with if not exists"):
|
||||
node.query(f"CREATE USER IF NOT EXISTS {user}")
|
||||
del user
|
||||
|
||||
with Scenario("I create user or replace, user does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Replace("1.0")]):
|
||||
user = "user0"
|
||||
with cleanup(user):
|
||||
with When(f"I create a user {user} with or replace"):
|
||||
node.query(f"CREATE USER OR REPLACE {user}")
|
||||
del user
|
||||
|
||||
with Scenario("I create user or replace, user does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Replace("1.0")]):
|
||||
user = "user0"
|
||||
with cleanup(user):
|
||||
create_user(user)
|
||||
with When(f"I create a user {user} with or replace"):
|
||||
node.query(f"CREATE USER OR REPLACE {user}")
|
||||
del user
|
||||
|
||||
with Scenario("I create user with no password", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Password_NoPassword("1.0")]):
|
||||
with cleanup("user1"):
|
||||
with When("I create a user with no password"):
|
||||
node.query("CREATE USER user1 IDENTIFIED WITH NO_PASSWORD")
|
||||
|
||||
with Scenario("I create user with plaintext password", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Password_PlainText("1.0")]):
|
||||
with cleanup("user1"):
|
||||
with When("I create a user with plaintext password"):
|
||||
node.query("CREATE USER user1 IDENTIFIED WITH PLAINTEXT_PASSWORD BY 'mypassword'")
|
||||
|
||||
with Scenario("I create user with sha256 password", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Password_Sha256Password("1.0")]):
|
||||
with cleanup("user2"):
|
||||
with When("I create a user with sha256 password"):
|
||||
password = hashlib.sha256("mypassword".encode("utf-8")).hexdigest()
|
||||
node.query(f"CREATE USER user2 IDENTIFIED WITH SHA256_PASSWORD BY '{password}'")
|
||||
|
||||
with Scenario("I create user with sha256 password using IDENTIFIED BY", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Password_Sha256Password("1.0")]):
|
||||
with cleanup("user2"):
|
||||
with When("I create a user with sha256 password using short form"):
|
||||
password = hashlib.sha256("mypassword".encode("utf-8")).hexdigest()
|
||||
node.query(f"CREATE USER user2 IDENTIFIED BY '{password}'")
|
||||
|
||||
with Scenario("I create user with sha256_hash password", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Password_Sha256Hash("1.0")]):
|
||||
with cleanup("user3"):
|
||||
with When("I create a user with sha256_hash"):
|
||||
def hash(password):
|
||||
return hashlib.sha256(password.encode("utf-8")).hexdigest()
|
||||
password = hash(hash("mypassword"))
|
||||
node.query(f"CREATE USER user3 IDENTIFIED WITH SHA256_HASH BY '{password}'")
|
||||
|
||||
with Scenario("I create user with double sha1 password", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Password("1.0")]):
|
||||
with cleanup("user3"):
|
||||
with When("I create a user with double_sha1_password"):
|
||||
node.query(f"CREATE USER user3 IDENTIFIED WITH DOUBLE_SHA1_PASSWORD BY 'mypassword'")
|
||||
|
||||
with Scenario("I create user with double sha1 hash", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Password_DoubleSha1Hash("1.0")]):
|
||||
with cleanup("user3"):
|
||||
with When("I create a user with double_sha1_hash"):
|
||||
def hash(password):
|
||||
return hashlib.sha1(password.encode("utf-8")).hexdigest()
|
||||
password = hash(hash("mypassword"))
|
||||
node.query(f"CREATE USER user3 IDENTIFIED WITH DOUBLE_SHA1_HASH BY '{password}'")
|
||||
|
||||
with Scenario("I create user with host name", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Host_Name("1.0")]):
|
||||
with cleanup("user4"):
|
||||
with When("I create a user with host name"):
|
||||
node.query("CREATE USER user4 HOST NAME 'localhost', NAME 'clickhouse.com'")
|
||||
|
||||
with Scenario("I create user with host regexp", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Host_Regexp("1.0")]):
|
||||
with cleanup("user5"):
|
||||
with When("I create a user with host regexp"):
|
||||
node.query("CREATE USER user5 HOST REGEXP 'lo.?*host', REGEXP 'lo*host'")
|
||||
|
||||
with Scenario("I create user with host ip", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Host_IP("1.0")]):
|
||||
with cleanup("user6"):
|
||||
with When("I create a user with host ip"):
|
||||
node.query("CREATE USER user6 HOST IP '127.0.0.1', IP '127.0.0.2'")
|
||||
|
||||
with Scenario("I create user with host like", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Host_Like("1.0")]):
|
||||
with cleanup("user7"):
|
||||
with When("I create a user with host like"):
|
||||
node.query("CREATE USER user7 HOST LIKE 'local%'")
|
||||
|
||||
with Scenario("I create user with host none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Host_None("1.0")]):
|
||||
with cleanup("user7"):
|
||||
with When("I create a user with host none"):
|
||||
node.query("CREATE USER user7 HOST NONE")
|
||||
|
||||
with Scenario("I create user with host local", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Host_Local("1.0")]):
|
||||
with cleanup("user7"):
|
||||
with When("I create a user with host local"):
|
||||
node.query("CREATE USER user7 HOST LOCAL")
|
||||
|
||||
with Scenario("I create user with host any", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Host_Any("1.0")]):
|
||||
with cleanup("user7"):
|
||||
with When("I create a user with host any"):
|
||||
node.query("CREATE USER user7 HOST ANY")
|
||||
|
||||
with Scenario("I create user with default role set to none", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_DefaultRole_None("1.0")]):
|
||||
with cleanup("user8"):
|
||||
with When("I create a user with no default role"):
|
||||
node.query("CREATE USER user8 DEFAULT ROLE NONE")
|
||||
|
||||
with Scenario("I create user with default role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_DefaultRole("1.0")]):
|
||||
with Given("I have a role"):
|
||||
node.query("CREATE ROLE default")
|
||||
with cleanup("user9"):
|
||||
with When("I create a user with a default role"):
|
||||
node.query("CREATE USER user9 DEFAULT ROLE default")
|
||||
with Finally("I drop the role"):
|
||||
node.query("DROP ROLE default")
|
||||
|
||||
with Scenario("I create user default role, role doesn't exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_DefaultRole("1.0")]):
|
||||
with cleanup("user12"):
|
||||
role = "role0"
|
||||
with Given(f"I ensure that role {role} does not exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with When(f"I create user with default role {role}"):
|
||||
exitcode, message = errors.role_not_found_in_disk(role)
|
||||
node.query(f"CREATE USER user12 DEFAULT ROLE {role}",exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create user default role, all except role doesn't exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_DefaultRole("1.0")]):
|
||||
with cleanup("user12"):
|
||||
role = "role0"
|
||||
with Given(f"I ensure that role {role} does not exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with When(f"I create user with default role {role}"):
|
||||
exitcode, message = errors.role_not_found_in_disk(role)
|
||||
node.query(f"CREATE USER user12 DEFAULT ROLE ALL EXCEPT {role}",exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I create user with all roles set to default", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_DefaultRole_All("1.0")]):
|
||||
with cleanup("user10"):
|
||||
with When("I create a user with all roles as default"):
|
||||
node.query("CREATE USER user10 DEFAULT ROLE ALL")
|
||||
|
||||
with Scenario("I create user with settings profile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Settings("1.0")]):
|
||||
with cleanup("user11"):
|
||||
with When("I create a user with a settings profile"):
|
||||
node.query("CREATE USER user11 SETTINGS PROFILE default, max_memory_usage=10000000 READONLY")
|
||||
|
||||
with Scenario("I create user settings profile, fake profile, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Settings("1.0")]):
|
||||
with cleanup("user18a"):
|
||||
profile = "profile0"
|
||||
with Given(f"I ensure that profile {profile} does not exist"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
with When(f"I create user with Settings and set profile to fake profile {profile}"):
|
||||
exitcode, message = errors.settings_profile_not_found_in_disk(profile)
|
||||
node.query("CREATE USER user18a SETTINGS PROFILE profile0", exitcode=exitcode, message=message)
|
||||
del profile
|
||||
|
||||
with Scenario("I create user settings with a fake setting, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Settings("1.0")]):
|
||||
with cleanup("user18b"):
|
||||
with When("I create settings profile using settings and nonexistent value"):
|
||||
exitcode, message = errors.unknown_setting("fake_setting")
|
||||
node.query("CREATE USER user18b SETTINGS fake_setting = 100000001", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I create user with settings without profile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_Settings("1.0")]):
|
||||
with cleanup("user12"):
|
||||
with When("I create a user with settings and no profile"):
|
||||
node.query("CREATE USER user12 SETTINGS max_memory_usage=10000000 READONLY")
|
||||
|
||||
with Scenario("I create user on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_OnCluster("1.0")]):
|
||||
try:
|
||||
with When("I create user on cluster"):
|
||||
node.query("CREATE USER user13 ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I drop the user"):
|
||||
node.query("DROP USER user13 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I create user on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Create_OnCluster("1.0")]):
|
||||
with When("I create user on fake cluster"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("CREATE USER user14 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
87
tests/testflows/rbac/tests/syntax/drop_quota.py
Executable file
87
tests/testflows/rbac/tests/syntax/drop_quota.py
Executable file
@ -0,0 +1,87 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("drop quota")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check drop quota query syntax.
|
||||
|
||||
```sql
|
||||
DROP QUOTA [IF EXISTS] name [,...] [ON CLUSTER cluster_name]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(quota):
|
||||
try:
|
||||
with Given("I have a quota"):
|
||||
node.query(f"CREATE QUOTA {quota}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the quota"):
|
||||
node.query(f"DROP QUOTA IF EXISTS {quota}")
|
||||
|
||||
def cleanup_quota(quota):
|
||||
with Given(f"I ensure that quota {quota} does not exist"):
|
||||
node.query(f"DROP QUOTA IF EXISTS {quota}")
|
||||
|
||||
with Scenario("I drop quota with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Drop("1.0")]):
|
||||
with cleanup("quota0"):
|
||||
with When("I run drop quota command"):
|
||||
node.query("DROP QUOTA quota0")
|
||||
|
||||
with Scenario("I drop quota, does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Drop("1.0")]):
|
||||
quota = "quota0"
|
||||
cleanup_quota(quota)
|
||||
with When("I run drop quota command, throws exception"):
|
||||
exitcode, message = errors.quota_not_found_in_disk(name=quota)
|
||||
node.query(f"DROP QUOTA {quota}", exitcode=exitcode, message=message)
|
||||
del quota
|
||||
|
||||
with Scenario("I drop quota if exists, quota exists", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Drop_IfExists("1.0")]):
|
||||
with cleanup("quota1"):
|
||||
with When("I run drop quota command"):
|
||||
node.query("DROP QUOTA IF EXISTS quota1")
|
||||
|
||||
with Scenario("I drop quota if exists, quota does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Drop_IfExists("1.0")]):
|
||||
cleanup_quota("quota2")
|
||||
with When("I run drop quota command, quota does not exist"):
|
||||
node.query("DROP QUOTA IF EXISTS quota2")
|
||||
|
||||
with Scenario("I drop default quota, throws error", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Drop("1.0")]):
|
||||
with When("I drop default quota"):
|
||||
exitcode, message = errors.cannot_remove_quota_default()
|
||||
node.query("DROP QUOTA default", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I drop multiple quotas", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Drop("1.0")]):
|
||||
with cleanup("quota2"), cleanup("quota3"):
|
||||
with When("I run drop quota command"):
|
||||
node.query("DROP QUOTA quota2, quota3")
|
||||
|
||||
with Scenario("I drop quota on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Drop_Cluster("1.0")]):
|
||||
try:
|
||||
with Given("I have a quota"):
|
||||
node.query("CREATE QUOTA quota4 ON CLUSTER sharded_cluster")
|
||||
with When("I run drop quota command"):
|
||||
node.query("DROP QUOTA quota4 ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I drop the quota in case it still exists"):
|
||||
node.query("DROP QUOTA IF EXISTS quota4 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I drop quota on fake cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_Drop_Cluster("1.0")]):
|
||||
with When("I run drop quota command"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("DROP QUOTA quota5 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
84
tests/testflows/rbac/tests/syntax/drop_role.py
Executable file
84
tests/testflows/rbac/tests/syntax/drop_role.py
Executable file
@ -0,0 +1,84 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("drop role")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check drop role query syntax.
|
||||
|
||||
```sql
|
||||
DROP ROLE [IF EXISTS] name [,...] [ON CLUSTER cluster_name]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(role):
|
||||
try:
|
||||
with Given("I have a role"):
|
||||
node.query(f"CREATE ROLE OR REPLACE {role}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I confirm the role is dropped"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
|
||||
def cleanup_role(role):
|
||||
with Given(f"I ensure that role {role} does not exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
|
||||
|
||||
with Scenario("I drop role with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Drop("1.0")]):
|
||||
with setup("role0"):
|
||||
with When("I drop role"):
|
||||
node.query("DROP ROLE role0")
|
||||
|
||||
with Scenario("I drop role that doesn't exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Drop("1.0")]):
|
||||
role = "role0"
|
||||
cleanup_role(role)
|
||||
with When(f"I drop role {role}"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name=role)
|
||||
node.query(f"DROP ROLE {role}", exitcode=exitcode, message=message)
|
||||
del role
|
||||
|
||||
with Scenario("I drop multiple roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Drop("1.0")]):
|
||||
with setup("role1"), setup("role2"):
|
||||
with When("I drop multiple roles"):
|
||||
node.query("DROP ROLE role1, role2")
|
||||
|
||||
with Scenario("I drop role that does not exist, using if exists", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Drop_IfExists("1.0")]):
|
||||
with When("I drop role if exists"):
|
||||
node.query("DROP ROLE IF EXISTS role3")
|
||||
|
||||
with Scenario("I drop multiple roles where one does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Drop_IfExists("1.0")]):
|
||||
with setup("role5"):
|
||||
with When("I drop multiple roles where one doesnt exist"):
|
||||
node.query("DROP ROLE IF EXISTS role3, role5")
|
||||
|
||||
with Scenario("I drop multiple roles where both do not exist", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Drop_IfExists("1.0")]):
|
||||
with Given("I ensure role does not exist"):
|
||||
node.query("DROP ROLE IF EXISTS role6")
|
||||
with When("I drop the nonexistant roles"):
|
||||
node.query("DROP USER IF EXISTS role5, role6")
|
||||
|
||||
with Scenario("I drop role on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Drop_Cluster("1.0")]):
|
||||
with Given("I have a role on cluster"):
|
||||
node.query("CREATE ROLE role0 ON CLUSTER sharded_cluster")
|
||||
with When("I drop the role from the cluster"):
|
||||
node.query("DROP ROLE role0 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I drop role on fake cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_Drop_Cluster("1.0")]):
|
||||
with When("I run drop role command"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("DROP ROLE role2 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
135
tests/testflows/rbac/tests/syntax/drop_row_policy.py
Executable file
135
tests/testflows/rbac/tests/syntax/drop_row_policy.py
Executable file
@ -0,0 +1,135 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("drop row policy")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check drop row policy query syntax.
|
||||
|
||||
```sql
|
||||
DROP [ROW] POLICY [IF EXISTS] name [,...] ON [database.]table [,...] [ON CLUSTER cluster_name]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(policy, on=["default.foo"]):
|
||||
try:
|
||||
with Given("I have a row policy"):
|
||||
for i in policy:
|
||||
for j in on:
|
||||
node.query(f"CREATE ROW POLICY OR REPLACE {i} ON {j}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the row policy"):
|
||||
for i in policy:
|
||||
for j in on:
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {i} ON {j}")
|
||||
|
||||
def cleanup_policy(policy, on="default.foo"):
|
||||
with Given(f"I ensure that policy {policy} does not exist"):
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {policy} ON {on}")
|
||||
|
||||
try:
|
||||
with Given("I have some tables"):
|
||||
node.query(f"CREATE TABLE default.foo (x UInt64, y String) Engine=Memory")
|
||||
node.query(f"CREATE TABLE default.foo2 (x UInt64, y String) Engine=Memory")
|
||||
|
||||
with Scenario("I drop row policy with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
with cleanup(["policy1"]):
|
||||
with When("I drop row policy"):
|
||||
node.query("DROP ROW POLICY policy1 ON default.foo")
|
||||
|
||||
with Scenario("I drop row policy using short syntax with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
with cleanup(["policy2"]):
|
||||
with When("I drop row policy short form"):
|
||||
node.query("DROP POLICY policy2 ON default.foo")
|
||||
|
||||
with Scenario("I drop row policy, does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
policy = "policy1"
|
||||
cleanup_policy(policy)
|
||||
with When("I drop row policy"):
|
||||
exitcode, message = errors.row_policy_not_found_in_disk(name=f"{policy} ON default.foo")
|
||||
node.query(f"DROP ROW POLICY {policy} ON default.foo", exitcode=exitcode, message=message)
|
||||
del policy
|
||||
|
||||
with Scenario("I drop row policy if exists, policy does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_IfExists("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
with cleanup(["policy3"]):
|
||||
with When("I drop row policy if exists"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy3 ON default.foo")
|
||||
|
||||
with Scenario("I drop row policy if exists, policy doesn't exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_IfExists("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
cleanup_policy("policy3")
|
||||
with When("I drop row policy if exists"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy3 ON default.foo")
|
||||
|
||||
with Scenario("I drop multiple row policies", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
with cleanup(["policy3", "policy4"]):
|
||||
with When("I drop multiple row policies"):
|
||||
node.query("DROP ROW POLICY policy3, policy4 ON default.foo")
|
||||
|
||||
with Scenario("I drop row policy on multiple tables", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
with cleanup(["policy3"], ["default.foo","default.foo2"]):
|
||||
with When("I drop row policy on multiple tables"):
|
||||
node.query("DROP ROW POLICY policy3 ON default.foo, default.foo2")
|
||||
|
||||
with Scenario("I drop multiple row policies on multiple tables", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
with cleanup(["policy3", "policy4"], ["default.foo","default.foo2"]):
|
||||
with When("I drop the row policies from the tables"):
|
||||
node.query("DROP ROW POLICY policy3 ON default.foo, policy4 ON default.foo2")
|
||||
|
||||
with Scenario("I drop row policy on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
try:
|
||||
with Given("I have a row policy"):
|
||||
node.query("CREATE ROW POLICY policy13 ON default.foo ON CLUSTER sharded_cluster")
|
||||
with When("I run drop row policy command"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy13 ON CLUSTER sharded_cluster ON default.foo")
|
||||
finally:
|
||||
with Finally("I drop the row policy in case it still exists"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy13 ON default.foo ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I drop row policy on cluster after table", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
try:
|
||||
with Given("I have a row policy"):
|
||||
node.query("CREATE ROW POLICY policy12 ON default.foo ON CLUSTER sharded_cluster")
|
||||
with When("I run drop row policy command"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy13 ON default.foo ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I drop the row policy in case it still exists"):
|
||||
node.query("DROP ROW POLICY IF EXISTS policy12 ON default.foo ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I drop row policy on fake cluster throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_RowPolicy_Drop_On("1.0")]):
|
||||
with When("I run drop row policy command"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("DROP ROW POLICY IF EXISTS policy14 ON default.foo ON CLUSTER fake_cluster",
|
||||
exitcode=exitcode, message=message)
|
||||
finally:
|
||||
with Finally("I drop the tables"):
|
||||
node.query(f"DROP TABLE IF EXISTS default.foo")
|
||||
node.query(f"DROP TABLE IF EXISTS default.foo2")
|
93
tests/testflows/rbac/tests/syntax/drop_settings_profile.py
Executable file
93
tests/testflows/rbac/tests/syntax/drop_settings_profile.py
Executable file
@ -0,0 +1,93 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("drop settings profile")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check drop settings profile query syntax.
|
||||
|
||||
```sql
|
||||
DROP [SETTINGS] PROFILE [IF EXISTS] name [,...] [ON CLUSTER cluster_name]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(profile):
|
||||
try:
|
||||
with Given("I have a settings profile"):
|
||||
node.query(f"CREATE SETTINGS PROFILE {profile}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the settings profile"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
|
||||
def cleanup_profile(profile):
|
||||
with Given(f"I ensure that profile {profile} does not exist"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
|
||||
with Scenario("I drop settings profile with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]):
|
||||
with cleanup("profile0"):
|
||||
with When("I drop settings profile"):
|
||||
node.query("DROP SETTINGS PROFILE profile0")
|
||||
|
||||
with Scenario("I drop settings profile, does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]):
|
||||
profile = "profile0"
|
||||
cleanup_profile(profile)
|
||||
with When("I drop settings profile"):
|
||||
exitcode, message = errors.settings_profile_not_found_in_disk(name=profile)
|
||||
node.query("DROP SETTINGS PROFILE profile0", exitcode=exitcode, message=message)
|
||||
del profile
|
||||
|
||||
with Scenario("I drop settings profile short form", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]):
|
||||
with cleanup("profile1"):
|
||||
with When("I drop settings profile short form"):
|
||||
node.query("DROP PROFILE profile1")
|
||||
|
||||
with Scenario("I drop settings profile if exists, profile does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop_IfExists("1.0")]):
|
||||
with cleanup("profile2"):
|
||||
with When("I drop settings profile if exists"):
|
||||
node.query("DROP SETTINGS PROFILE IF EXISTS profile2")
|
||||
|
||||
with Scenario("I drop settings profile if exists, profile does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop_IfExists("1.0")]):
|
||||
cleanup_profile("profile2")
|
||||
with When("I drop settings profile if exists"):
|
||||
node.query("DROP SETTINGS PROFILE IF EXISTS profile2")
|
||||
|
||||
with Scenario("I drop default settings profile, throws error", requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]):
|
||||
with When("I drop default profile"):
|
||||
exitcode, message = errors.cannot_remove_settings_profile_default()
|
||||
node.query("DROP SETTINGS PROFILE default", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I drop multiple settings profiles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop("1.0")]):
|
||||
with cleanup("profile3"), cleanup("profile4"):
|
||||
with When("I drop multiple settings profiles"):
|
||||
node.query("DROP SETTINGS PROFILE profile3, profile4")
|
||||
|
||||
with Scenario("I drop settings profile on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop_OnCluster("1.0")]):
|
||||
try:
|
||||
with Given("I have a settings profile"):
|
||||
node.query("CREATE SETTINGS PROFILE profile5 ON CLUSTER sharded_cluster")
|
||||
with When("I run drop settings profile command"):
|
||||
node.query("DROP SETTINGS PROFILE profile5 ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I drop the profile in case it still exists"):
|
||||
node.query("DROP SETTINGS PROFILE IF EXISTS profile5 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I drop settings profile on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_Drop_OnCluster("1.0")]):
|
||||
with When("I run drop settings profile command"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("DROP SETTINGS PROFILE profile6 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
98
tests/testflows/rbac/tests/syntax/drop_user.py
Executable file
98
tests/testflows/rbac/tests/syntax/drop_user.py
Executable file
@ -0,0 +1,98 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("drop user")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check drop user query syntax.
|
||||
|
||||
```sql
|
||||
DROP USER [IF EXISTS] name [,...] [ON CLUSTER cluster_name]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(user):
|
||||
try:
|
||||
with Given("I have a user"):
|
||||
node.query(f"CREATE USER {user}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the user"):
|
||||
node.query(f"DROP USER IF EXISTS {user}")
|
||||
|
||||
def cleanup_user(user):
|
||||
with Given(f"I ensure that user {user} does not exist"):
|
||||
node.query(f"DROP USER IF EXISTS {user}")
|
||||
|
||||
with Scenario("I drop user with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop("1.0")]):
|
||||
with setup("user0"):
|
||||
with When("I drop user"):
|
||||
node.query("DROP USER user0")
|
||||
|
||||
with Scenario("I drop user, does not exist, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop("1.0")]):
|
||||
user = "user0"
|
||||
cleanup_user(user)
|
||||
with When(f"I drop user {user}"):
|
||||
exitcode, message = errors.user_not_found_in_disk(name=user)
|
||||
node.query(f"DROP USER {user}", exitcode=exitcode, message=message)
|
||||
del user
|
||||
|
||||
with Scenario("I drop multiple users", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop("1.0")]):
|
||||
with setup("user1"), setup("user2"):
|
||||
with When("I drop multiple users"):
|
||||
node.query("DROP USER user1, user2")
|
||||
|
||||
with Scenario("I drop user if exists, user does exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop_IfExists("1.0")]):
|
||||
with setup("user3"):
|
||||
with When("I drop user that exists"):
|
||||
node.query("DROP USER IF EXISTS user3")
|
||||
|
||||
with Scenario("I drop user if exists, user does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop_IfExists("1.0")]):
|
||||
cleanup_user("user3")
|
||||
with When("I drop nonexistant user"):
|
||||
node.query("DROP USER IF EXISTS user3")
|
||||
|
||||
with Scenario("I drop default user, throws error", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop("1.0")]):
|
||||
with When("I drop user"):
|
||||
exitcode, message = errors.cannot_remove_user_default()
|
||||
node.query("DROP USER default", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I drop multiple users where one does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop_IfExists("1.0")]):
|
||||
with setup("user3"):
|
||||
with When("I drop multiple users where one does not exist"):
|
||||
node.query("DROP USER IF EXISTS user3, user4")
|
||||
|
||||
with Scenario("I drop multiple users where both do not exist", requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop_IfExists("1.0")]):
|
||||
with When("I drop the nonexistant users"):
|
||||
node.query("DROP USER IF EXISTS user5, user6")
|
||||
|
||||
with Scenario("I drop user from specific cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop_OnCluster("1.0")]):
|
||||
try:
|
||||
with Given("I have a user on cluster"):
|
||||
node.query("CREATE USER user4 ON CLUSTER sharded_cluster")
|
||||
with When("I drop a user from the cluster"):
|
||||
node.query("DROP USER user4 ON CLUSTER sharded_cluster")
|
||||
finally:
|
||||
with Finally("I make sure the user is dropped"):
|
||||
node.query("DROP USER IF EXISTS user4 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I drop user from fake cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_Drop_OnCluster("1.0")]):
|
||||
with When("I drop a user from the fake cluster"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("DROP USER user5 ON CLUSTER fake_cluster", exitcode=exitcode, message=message)
|
34
tests/testflows/rbac/tests/syntax/feature.py
Executable file
34
tests/testflows/rbac/tests/syntax/feature.py
Executable file
@ -0,0 +1,34 @@
|
||||
from testflows.core import *
|
||||
|
||||
@TestFeature
|
||||
@Name("syntax")
|
||||
def feature(self):
|
||||
Feature(run=load("rbac.tests.syntax.create_user", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.alter_user", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.drop_user", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.show_create_user", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.create_role", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.alter_role", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.drop_role", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.show_create_role", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.grant_role", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.grant_privilege","feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.show_grants", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.revoke_role", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.revoke_privilege","feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.create_row_policy", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.alter_row_policy", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.drop_row_policy", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.show_create_row_policy", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.show_row_policies", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.create_quota", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.alter_quota", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.drop_quota", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.show_create_quota", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.show_quotas", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.create_settings_profile", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.alter_settings_profile", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.drop_settings_profile", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.show_create_settings_profile", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.set_default_role", "feature"), flags=TE)
|
||||
Feature(run=load("rbac.tests.syntax.set_role","feature"), flags=TE)
|
134
tests/testflows/rbac/tests/syntax/grant_privilege.py
Executable file
134
tests/testflows/rbac/tests/syntax/grant_privilege.py
Executable file
@ -0,0 +1,134 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@contextmanager
|
||||
def setup(node):
|
||||
try:
|
||||
with Given("I have some users and roles"):
|
||||
node.query("CREATE USER OR REPLACE user0 ON CLUSTER sharded_cluster")
|
||||
node.query("CREATE USER OR REPLACE user1")
|
||||
node.query("CREATE ROLE OR REPLACE role1")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the users and roles"):
|
||||
node.query("DROP USER IF EXISTS user0 ON CLUSTER sharded_cluster")
|
||||
node.query("DROP USER IF EXISTS user1")
|
||||
node.query("DROP ROLE IF EXISTS role1")
|
||||
|
||||
|
||||
@TestOutline(Scenario)
|
||||
@Examples("privilege on allow_introspection", [
|
||||
("dictGet", ("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_DictGet("1.0"))),
|
||||
("INTROSPECTION", ("*.*",), True, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Introspection("1.0"))),
|
||||
("SELECT", ("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Select("1.0"))),
|
||||
("INSERT",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Insert("1.0"))),
|
||||
("ALTER",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Alter("1.0"))),
|
||||
("CREATE",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Create("1.0"))),
|
||||
("DROP",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Drop("1.0"))),
|
||||
("TRUNCATE",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Truncate("1.0"))),
|
||||
("OPTIMIZE",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Optimize("1.0"))),
|
||||
("SHOW",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Show("1.0"))),
|
||||
("KILL QUERY",("*.*",), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_KillQuery("1.0"))),
|
||||
("ACCESS MANAGEMENT",("*.*",), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_AccessManagement("1.0"))),
|
||||
("SYSTEM",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_System("1.0"))),
|
||||
("SOURCES",("*.*",), False, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_Sources("1.0"))),
|
||||
("ALL",("*.*",), True, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_All("1.0"))),
|
||||
("ALL PRIVILEGES",("*.*",), True, Requirements(RQ_SRS_006_RBAC_Grant_Privilege_All("1.0"))), #alias for all
|
||||
],)
|
||||
def grant_privileges(self, privilege, on, allow_introspection, node="clickhouse1"):
|
||||
grant_privilege(privilege=privilege, on=on, allow_introspection=allow_introspection, node=node)
|
||||
|
||||
@TestOutline(Scenario)
|
||||
@Requirements(RQ_SRS_006_RBAC_Grant_Privilege_GrantOption("1.0"))
|
||||
def grant_privilege(self, privilege, on, allow_introspection, node="clickhouse1"):
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
for on_ in on:
|
||||
with When(f"I grant {privilege} privilege to user on {on_}"):
|
||||
with setup(node):
|
||||
settings = []
|
||||
if allow_introspection:
|
||||
settings.append(("allow_introspection_functions", 1))
|
||||
node.query("SET allow_introspection_functions = 1")
|
||||
with When("I grant privilege without grant option"):
|
||||
node.query(f"GRANT {privilege} ON {on_} TO user0", settings=settings)
|
||||
with When("I grant privilege with grant option"):
|
||||
node.query(f"GRANT {privilege} ON {on_} TO user1 WITH GRANT OPTION", settings=settings)
|
||||
|
||||
#grant column specific for some column 'x'
|
||||
with When("I grant privilege with columns"):
|
||||
node.query(f"GRANT {privilege}(x) ON {on_} TO user0", settings=settings)
|
||||
|
||||
@TestFeature
|
||||
@Name("grant privilege")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check grant privilege syntax.
|
||||
|
||||
```sql
|
||||
GRANT [ON CLUSTER cluster_name]
|
||||
privilege {SELECT | SELECT(columns) | INSERT | ALTER | CREATE | DROP | TRUNCATE | OPTIMIZE | SHOW | KILL QUERY | ACCESS MANAGEMENT | SYSTEM | INTROSPECTION | SOURCES | dictGet | NONE |ALL [PRIVILEGES]} [, ...]
|
||||
ON {*.* | database.* | database.table | * | table}
|
||||
TO {user | role | CURRENT_USER} [,...]
|
||||
[WITH GRANT OPTION]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
Scenario(run=grant_privileges)
|
||||
|
||||
# with nonexistant object name, GRANT assumes type role
|
||||
with Scenario("I grant privilege to role that does not exist", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]):
|
||||
with Given("I ensure that role does not exist"):
|
||||
node.query("DROP ROLE IF EXISTS role0")
|
||||
with When("I grant privilege ON CLUSTER"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="role0")
|
||||
node.query("GRANT NONE TO role0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I grant privilege ON CLUSTER", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_OnCluster("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I grant privilege ON CLUSTER"):
|
||||
node.query("GRANT ON CLUSTER sharded_cluster NONE TO user0")
|
||||
|
||||
with Scenario("I grant privilege on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_OnCluster("1.0")]):
|
||||
with setup(node):
|
||||
with When("I grant privilege ON CLUSTER"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("GRANT ON CLUSTER fake_cluster NONE TO user0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I grant privilege to multiple users and roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_To("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I grant privilege to several users"):
|
||||
node.query("GRANT NONE TO user0, user1, role1")
|
||||
|
||||
with Scenario("I grant privilege to current user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_ToCurrentUser("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I grant privilege to current user"):
|
||||
node.query("GRANT NONE TO CURRENT_USER", settings = [("user","user0")])
|
||||
|
||||
with Scenario("I grant privilege NONE to default user, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_ToCurrentUser("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I grant privilege to current user"):
|
||||
exitcode, message = errors.cannot_update_default()
|
||||
node.query("GRANT NONE TO CURRENT_USER", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I grant privilege with grant option", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_GrantOption("1.0"),
|
||||
RQ_SRS_006_RBAC_Grant_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I grant privilege with grant option"):
|
||||
node.query("GRANT NONE ON *.* TO user0 WITH GRANT OPTION")
|
115
tests/testflows/rbac/tests/syntax/grant_role.py
Executable file
115
tests/testflows/rbac/tests/syntax/grant_role.py
Executable file
@ -0,0 +1,115 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("grant role")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check grant query syntax.
|
||||
|
||||
```sql
|
||||
GRANT ON CLUSTER [cluster_name] role [,...] TO {user | another_role | CURRENT_USER} [,...] [WITH ADMIN OPTION]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(users=0,roles=0):
|
||||
try:
|
||||
with Given("I have some users and roles"):
|
||||
for i in range(users):
|
||||
node.query(f"CREATE USER OR REPLACE user{i}")
|
||||
for j in range(roles):
|
||||
node.query(f"CREATE ROLE OR REPLACE role{j}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the users and roles"):
|
||||
for i in range(users):
|
||||
node.query(f"DROP USER IF EXISTS user{i}")
|
||||
for j in range(roles):
|
||||
node.query(f"DROP ROLE IF EXISTS role{j}")
|
||||
|
||||
with Scenario("I grant a role to a user",flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role("1.0")]):
|
||||
with setup(1,1):
|
||||
with When("I grant a role"):
|
||||
node.query("GRANT role0 TO user0")
|
||||
|
||||
with Scenario("I grant a nonexistent role to user", requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role("1.0")]):
|
||||
with setup(1,0):
|
||||
with When("I grant nonexistent role to a user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="role0")
|
||||
node.query("GRANT role0 TO user0", exitcode=exitcode, message=message)
|
||||
|
||||
# with nonexistent object name, GRANT assumes type role (treats user0 as role)
|
||||
with Scenario("I grant a role to a nonexistent user", requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role("1.0")]):
|
||||
with setup(0,1):
|
||||
with When("I grant role to a nonexistent user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="user0")
|
||||
node.query("GRANT role0 TO user0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I grant a nonexistent role to a nonexistent user", requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role("1.0")]):
|
||||
with setup(0,0):
|
||||
with When("I grant nonexistent role to a nonexistent user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="role0")
|
||||
node.query("GRANT role0 TO user0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I grant a role to multiple users", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role("1.0")]):
|
||||
with setup(2,1):
|
||||
with When("I grant role to a multiple users"):
|
||||
node.query("GRANT role0 TO user0, user1")
|
||||
|
||||
with Scenario("I grant multiple roles to multiple users", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role("1.0")]):
|
||||
with setup(2,2):
|
||||
with When("I grant multiple roles to multiple users"):
|
||||
node.query("GRANT role0, role1 TO user0, user1")
|
||||
|
||||
with Scenario("I grant role to current user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role_CurrentUser("1.0")]):
|
||||
with setup(1,1):
|
||||
with Given("I have a user with access management privilege"):
|
||||
node.query("GRANT ACCESS MANAGEMENT ON *.* TO user0")
|
||||
with When("I grant role to current user"):
|
||||
node.query("GRANT role0 TO CURRENT_USER", settings = [("user","user0")])
|
||||
|
||||
with Scenario("I grant role to default user, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role_CurrentUser("1.0")]):
|
||||
with setup(1,1):
|
||||
with When("I grant role to default user"):
|
||||
exitcode, message = errors.cannot_update_default()
|
||||
node.query("GRANT role0 TO CURRENT_USER", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I grant role to user with admin option", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role_AdminOption("1.0")]):
|
||||
with setup(1,1):
|
||||
with When("I grant role to a user with admin option"):
|
||||
node.query("GRANT role0 TO user0 WITH ADMIN OPTION")
|
||||
|
||||
with Scenario("I grant role to user on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role_OnCluster("1.0")]):
|
||||
try:
|
||||
with Given("I have a user and a role on a cluster"):
|
||||
node.query("CREATE USER user0 ON CLUSTER sharded_cluster")
|
||||
node.query("CREATE ROLE role0 ON CLUSTER sharded_cluster")
|
||||
with When("I grant the role to the user"):
|
||||
node.query("GRANT ON CLUSTER sharded_cluster role0 TO user0")
|
||||
finally:
|
||||
with Finally("I drop the user and role"):
|
||||
node.query("DROP USER user0 ON CLUSTER sharded_cluster")
|
||||
node.query("DROP ROLE role0 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I grant role to user on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Grant_Role_OnCluster("1.0")]):
|
||||
with setup(1,1):
|
||||
with When("I grant the role to the user"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("GRANT ON CLUSTER fake_cluster role0 TO user0", exitcode=exitcode, message=message)
|
159
tests/testflows/rbac/tests/syntax/revoke_privilege.py
Executable file
159
tests/testflows/rbac/tests/syntax/revoke_privilege.py
Executable file
@ -0,0 +1,159 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@contextmanager
|
||||
def setup(node):
|
||||
try:
|
||||
with Given("I have some users and roles"):
|
||||
node.query("CREATE USER OR REPLACE user0 ON CLUSTER sharded_cluster")
|
||||
node.query("CREATE USER OR REPLACE user1")
|
||||
node.query("CREATE ROLE OR REPLACE role1")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the users and roles"):
|
||||
node.query("DROP USER IF EXISTS user0 ON CLUSTER sharded_cluster")
|
||||
node.query("DROP USER IF EXISTS user1")
|
||||
node.query("DROP ROLE IF EXISTS role1")
|
||||
|
||||
|
||||
@TestOutline(Scenario)
|
||||
@Examples("privilege on allow_introspection", [
|
||||
("dictGet", ("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_DictGet("1.0"))),
|
||||
("INTROSPECTION", ("*.*",), True, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Introspection("1.0"))),
|
||||
("SELECT", ("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Select("1.0"))),
|
||||
("INSERT",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Insert("1.0"))),
|
||||
("ALTER",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Alter("1.0"))),
|
||||
("CREATE",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Create("1.0"))),
|
||||
("DROP",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Drop("1.0"))),
|
||||
("TRUNCATE",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Truncate("1.0"))),
|
||||
("OPTIMIZE",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Optimize("1.0"))),
|
||||
("SHOW",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Show("1.0"))),
|
||||
("KILL QUERY",("*.*",), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_KillQuery("1.0"))),
|
||||
("ACCESS MANAGEMENT",("*.*",), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_AccessManagement("1.0"))),
|
||||
("SYSTEM",("db0.table0","db0.*","*.*","tb0","*"), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_System("1.0"))),
|
||||
("SOURCES",("*.*",), False, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_Sources("1.0"))),
|
||||
("ALL",("*.*",), True, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_All("1.0"))),
|
||||
("ALL PRIVILEGES",("*.*",), True, Requirements(RQ_SRS_006_RBAC_Revoke_Privilege_All("1.0"))), #alias for all
|
||||
],)
|
||||
def revoke_privileges(self, privilege, on, allow_introspection, node="clickhouse1"):
|
||||
revoke_privilege(privilege=privilege, on=on, allow_introspection=allow_introspection, node=node)
|
||||
|
||||
@TestOutline(Scenario)
|
||||
@Requirements([RQ_SRS_006_RBAC_Revoke_Privilege_Any("1.0") , RQ_SRS_006_RBAC_Revoke_Privilege_PrivelegeColumns("1.0")])
|
||||
def revoke_privilege(self, privilege, on, allow_introspection, node="clickhouse1"):
|
||||
node = self.context.cluster.node(node)
|
||||
for on_ in on:
|
||||
with When(f"I revoke {privilege} privilege from user on {on_}"):
|
||||
with setup(node):
|
||||
settings = []
|
||||
if allow_introspection:
|
||||
settings.append(("allow_introspection_functions", 1))
|
||||
node.query("SET allow_introspection_functions = 1")
|
||||
with When("I revoke privilege without columns"):
|
||||
node.query(f"REVOKE {privilege} ON {on_} FROM user0", settings=settings)
|
||||
|
||||
#revoke column specific for some column 'x'
|
||||
with When("I revoke privilege with columns"):
|
||||
node.query(f"REVOKE {privilege}(x) ON {on_} FROM user0", settings=settings)
|
||||
|
||||
@TestFeature
|
||||
@Name("revoke privilege")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check revoke privilege syntax.
|
||||
|
||||
```sql
|
||||
REVOKE [ON CLUSTER cluster_name] privilege
|
||||
[(column_name [,...])] [,...]
|
||||
ON {db.table|db.*|*.*|table|*}
|
||||
FROM {user | CURRENT_USER} [,...] | ALL | ALL EXCEPT {user | CURRENT_USER} [,...]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
Scenario(run=revoke_privileges)
|
||||
|
||||
with Scenario("I revoke privilege ON CLUSTER", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Cluster("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I revoke privilege ON CLUSTER"):
|
||||
node.query("REVOKE ON CLUSTER sharded_cluster NONE FROM user0")
|
||||
|
||||
with Scenario("I revoke privilege ON fake CLUSTER, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_Cluster("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I revoke privilege ON CLUSTER"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("REVOKE ON CLUSTER fake_cluster NONE FROM user0",
|
||||
exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I revoke privilege from multiple users and roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I revoke privilege from multiple users"):
|
||||
node.query("REVOKE NONE FROM user0, user1, role1")
|
||||
|
||||
with Scenario("I revoke privilege from current user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I revoke privilege from current user"):
|
||||
node.query("REVOKE NONE FROM CURRENT_USER", settings = [("user","user0")])
|
||||
|
||||
with Scenario("I revoke privilege from all users", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I revoke privilege from all users"):
|
||||
exitcode, message = errors.cannot_update_default()
|
||||
node.query("REVOKE NONE FROM ALL", exitcode=exitcode,message=message)
|
||||
|
||||
with Scenario("I revoke privilege from default user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I revoke privilege from default user"):
|
||||
exitcode, message = errors.cannot_update_default()
|
||||
node.query("REVOKE NONE FROM default", exitcode=exitcode,message=message)
|
||||
|
||||
#By default, ClickHouse treats unnamed object as role
|
||||
with Scenario("I revoke privilege from nonexistent role, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
role = "role5"
|
||||
with Given(f"I ensure that role {role} does not exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with When(f"I revoke privilege from nonexistent role {role}"):
|
||||
exitcode, message = errors.role_not_found_in_disk(role)
|
||||
node.query(f"REVOKE NONE FROM {role}", exitcode=exitcode,message=message)
|
||||
|
||||
with Scenario("I revoke privilege from ALL EXCEPT nonexistent role, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
role = "role5"
|
||||
with Given(f"I ensure that role {role} does not exist"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
with When(f"I revoke privilege from nonexistent role {role}"):
|
||||
exitcode, message = errors.role_not_found_in_disk(role)
|
||||
node.query(f"REVOKE NONE FROM ALL EXCEPT {role}", exitcode=exitcode,message=message)
|
||||
|
||||
with Scenario("I revoke privilege from all except some users and roles", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I revoke privilege all except some users"):
|
||||
node.query("REVOKE NONE FROM ALL EXCEPT default, user0, role1")
|
||||
|
||||
with Scenario("I revoke privilege from all except current user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_From("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Privilege_None("1.0")]):
|
||||
with setup(node):
|
||||
with When("I revoke privilege from all except current user"):
|
||||
node.query("REVOKE NONE FROM ALL EXCEPT CURRENT_USER")
|
198
tests/testflows/rbac/tests/syntax/revoke_role.py
Executable file
198
tests/testflows/rbac/tests/syntax/revoke_role.py
Executable file
@ -0,0 +1,198 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("revoke role")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check revoke query syntax.
|
||||
|
||||
```sql
|
||||
REVOKE [ON CLUSTER cluster_name] [ADMIN OPTION FOR]
|
||||
role [,...] FROM {user | role | CURRENT_USER} [,...]
|
||||
| ALL | ALL EXCEPT {user_name | role_name | CURRENT_USER} [,...]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(users=2,roles=2):
|
||||
try:
|
||||
with Given("I have some users"):
|
||||
for i in range(users):
|
||||
node.query(f"CREATE USER OR REPLACE user{i}")
|
||||
with And("I have some roles"):
|
||||
for i in range(roles):
|
||||
node.query(f"CREATE ROLE OR REPLACE role{i}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the users"):
|
||||
for i in range(users):
|
||||
node.query(f"DROP USER IF EXISTS user{i}")
|
||||
with And("I drop the roles"):
|
||||
for i in range(roles):
|
||||
node.query(f"DROP ROLE IF EXISTS role{i}")
|
||||
|
||||
with Scenario("I revoke a role from a user",flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role"):
|
||||
node.query("REVOKE role0 FROM user0")
|
||||
|
||||
with Scenario("I revoke a nonexistent role from user", requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup(1,0):
|
||||
with When("I revoke nonexistent role from a user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="role0")
|
||||
node.query("REVOKE role0 FROM user0", exitcode=exitcode, message=message)
|
||||
|
||||
# with nonexistent object name, REVOKE assumes type role (treats user0 as role)
|
||||
with Scenario("I revoke a role from a nonexistent user", requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup(0,1):
|
||||
with When("I revoke role from a nonexistent user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="user0")
|
||||
node.query("REVOKE role0 FROM user0", exitcode=exitcode, message=message)
|
||||
|
||||
# with nonexistent object name, REVOKE assumes type role (treats user0 as role)
|
||||
with Scenario("I revoke a role from ALL EXCEPT nonexistent user", requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup(0,1):
|
||||
with When("I revoke role from a nonexistent user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="user0")
|
||||
node.query("REVOKE role0 FROM ALL EXCEPT user0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I revoke a nonexistent role from a nonexistent user", requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup(0,0):
|
||||
with When("I revoke nonexistent role from a nonexistent user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="role0")
|
||||
node.query("REVOKE role0 FROM user0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I revoke a role from multiple users", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role from multiple users"):
|
||||
node.query("REVOKE role0 FROM user0, user1")
|
||||
|
||||
with Scenario("I revoke multiple roles from multiple users", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup():
|
||||
node.query("REVOKE role0, role1 FROM user0, user1")
|
||||
|
||||
#user is default, expect exception
|
||||
with Scenario("I revoke a role from default user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role from default user"):
|
||||
exitcode, message = errors.cannot_update_default()
|
||||
node.query("REVOKE role0 FROM CURRENT_USER", exitcode=exitcode, message=message)
|
||||
|
||||
#user is user0
|
||||
with Scenario("I revoke a role from current user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role from current user"):
|
||||
node.query("REVOKE role0 FROM CURRENT_USER", settings = [("user","user0")])
|
||||
|
||||
#user is default, expect exception
|
||||
with Scenario("I revoke a role from all", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role from all"):
|
||||
exitcode, message = errors.cannot_update_default()
|
||||
node.query("REVOKE role0 FROM ALL", exitcode=exitcode, message=message)
|
||||
|
||||
#user is default, expect exception
|
||||
with Scenario("I revoke multiple roles from all", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke multiple roles from all"):
|
||||
exitcode, message = errors.cannot_update_default()
|
||||
node.query("REVOKE role0, role1 FROM ALL", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I revoke a role from all but current user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role from all except current"):
|
||||
node.query("REVOKE role0 FROM ALL EXCEPT CURRENT_USER")
|
||||
|
||||
with Scenario("I revoke a role from all but default user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role from all except default"):
|
||||
node.query("REVOKE role0 FROM ALL EXCEPT default",
|
||||
settings = [("user","user0")])
|
||||
|
||||
with Scenario("I revoke multiple roles from all but default user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Keywords("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke multiple roles from all except default"):
|
||||
node.query("REVOKE role0, role1 FROM ALL EXCEPT default", settings = [("user","user0")])
|
||||
|
||||
with Scenario("I revoke a role from a role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role from a role"):
|
||||
node.query("REVOKE role0 FROM role1")
|
||||
|
||||
with Scenario("I revoke a role from a role and a user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke a role from multiple roles"):
|
||||
node.query("REVOKE role0 FROM role1, user0")
|
||||
|
||||
with Scenario("I revoke a role from a user on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Cluster("1.0")]):
|
||||
with Given("I have a role and a user on a cluster"):
|
||||
node.query("CREATE USER OR REPLACE user0 ON CLUSTER sharded_cluster")
|
||||
node.query("CREATE ROLE OR REPLACE role0 ON CLUSTER sharded_cluster")
|
||||
with When("I revoke a role from user on a cluster"):
|
||||
node.query("REVOKE ON CLUSTER sharded_cluster role0 FROM user0")
|
||||
with Finally("I drop the user and role"):
|
||||
node.query("DROP USER IF EXISTS user0 ON CLUSTER sharded_cluster")
|
||||
node.query("DROP ROLE IF EXISTS role0 ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I revoke a role on fake cluster, throws exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Cluster("1.0")]):
|
||||
with When("I revoke a role from user on a cluster"):
|
||||
exitcode, message = errors.cluster_not_found("fake_cluster")
|
||||
node.query("REVOKE ON CLUSTER fake_cluster role0 FROM user0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I revoke multiple roles from multiple users on cluster", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_Role_Cluster("1.0")]):
|
||||
with Given("I have multiple roles and multiple users on a cluster"):
|
||||
for i in range(2):
|
||||
node.query(f"CREATE USER OR REPLACE user{i} ON CLUSTER sharded_cluster")
|
||||
node.query(f"CREATE ROLE OR REPLACE role{i} ON CLUSTER sharded_cluster")
|
||||
with When("I revoke multiple roles from multiple users on cluster"):
|
||||
node.query("REVOKE ON CLUSTER sharded_cluster role0, role1 FROM user0, user1")
|
||||
with Finally("I drop the roles and users"):
|
||||
for i in range(2):
|
||||
node.query(f"DROP USER IF EXISTS user{i} ON CLUSTER sharded_cluster")
|
||||
node.query(f"DROP ROLE IF EXISTS role{i} ON CLUSTER sharded_cluster")
|
||||
|
||||
with Scenario("I revoke admin option for role from a user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_AdminOption("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke admin option for role from a user"):
|
||||
node.query("REVOKE ADMIN OPTION FOR role0 FROM user0")
|
||||
|
||||
with Scenario("I revoke admin option for multiple roles from multiple users", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Revoke_Role("1.0"),
|
||||
RQ_SRS_006_RBAC_Revoke_AdminOption("1.0")]):
|
||||
with setup():
|
||||
with When("I revoke admin option for multiple roles from multiple users"):
|
||||
node.query("REVOKE ADMIN OPTION FOR role0, role1 FROM user0, user1")
|
120
tests/testflows/rbac/tests/syntax/set_default_role.py
Executable file
120
tests/testflows/rbac/tests/syntax/set_default_role.py
Executable file
@ -0,0 +1,120 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("set default role")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check set default role query syntax.
|
||||
|
||||
```sql
|
||||
SET DEFAULT ROLE {NONE | role [,...] | ALL | ALL EXCEPT role [,...]} TO {user|CURRENT_USER} [,...]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(users=2,roles=2):
|
||||
try:
|
||||
with Given("I have some users"):
|
||||
for i in range(users):
|
||||
node.query(f"CREATE USER OR REPLACE user{i}")
|
||||
with And("I have some roles"):
|
||||
for i in range(roles):
|
||||
node.query(f"CREATE ROLE OR REPLACE role{i}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the users"):
|
||||
for i in range(users):
|
||||
node.query(f"DROP USER IF EXISTS user{i}")
|
||||
with And("I drop the roles"):
|
||||
for i in range(roles):
|
||||
node.query(f"DROP ROLE IF EXISTS role{i}")
|
||||
|
||||
with Scenario("I set default a nonexistent role to user", requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole("1.0")]):
|
||||
with setup(1,0):
|
||||
with When("I set default nonexistent role to a user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="role0")
|
||||
node.query("SET DEFAULT ROLE role0 TO user0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I set default ALL EXCEPT a nonexistent role to user", requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole("1.0")]):
|
||||
with setup(1,0):
|
||||
with When("I set default nonexistent role to a user"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="role0")
|
||||
node.query("SET DEFAULT ROLE ALL EXCEPT role0 TO user0", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I set default a role to a nonexistent user", requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole("1.0")]):
|
||||
with setup(0,1):
|
||||
with When("I set default role to a nonexistent user"):
|
||||
exitcode, message = errors.user_not_found_in_disk(name="user0")
|
||||
node.query("SET DEFAULT ROLE role0 TO user0", exitcode=exitcode, message=message)
|
||||
|
||||
#in SET DEFAULT ROLE, the nonexistent user is noticed first and becomes the thrown exception
|
||||
with Scenario("I set default a nonexistent role to a nonexistent user", requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole("1.0")]):
|
||||
with setup(0,0):
|
||||
with When("I set default nonexistent role to a nonexistent user"):
|
||||
exitcode, message = errors.user_not_found_in_disk(name="user0")
|
||||
node.query("SET DEFAULT ROLE role0 TO user0", exitcode=exitcode, message=message)
|
||||
|
||||
try:
|
||||
with Given("I have some roles and some users"):
|
||||
for i in range(2):
|
||||
node.query(f"CREATE ROLE role{i}")
|
||||
node.query(f"CREATE USER user{i}")
|
||||
node.query(f"GRANT role0, role1 TO user0, user1")
|
||||
|
||||
with Scenario("I set default role for a user to none", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole_None("1.0")]):
|
||||
with When("I set no roles default for user"):
|
||||
node.query("SET DEFAULT ROLE NONE TO user0")
|
||||
|
||||
with Scenario("I set one default role for a user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole("1.0")]):
|
||||
with When("I set a default role for user "):
|
||||
node.query("SET DEFAULT ROLE role0 TO user0")
|
||||
|
||||
with Scenario("I set one default role for user default, throws exception", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole("1.0")]):
|
||||
with When("I set a default role for default"):
|
||||
exitcode, message = errors.cannot_update_default()
|
||||
node.query("SET DEFAULT ROLE role0 TO default", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I set multiple default roles for a user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole("1.0")]):
|
||||
with When("I set multiple default roles to user"):
|
||||
node.query("SET DEFAULT ROLE role0, role1 TO user0")
|
||||
|
||||
with Scenario("I set multiple default roles for multiple users", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole("1.0")]):
|
||||
with When("I set multiple default roles to multiple users"):
|
||||
node.query("SET DEFAULT ROLE role0, role1 TO user0, user1")
|
||||
|
||||
with Scenario("I set all roles as default for a user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole_All("1.0")]):
|
||||
with When("I set all roles default to user"):
|
||||
node.query("SET DEFAULT ROLE ALL TO user0")
|
||||
|
||||
with Scenario("I set all roles except one for a user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole_AllExcept("1.0")]):
|
||||
with When("I set all except one role default to user"):
|
||||
node.query("SET DEFAULT ROLE ALL EXCEPT role0 TO user0")
|
||||
|
||||
with Scenario("I set default role for current user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetDefaultRole_CurrentUser("1.0")]):
|
||||
with When("I set default role to current user"):
|
||||
node.query("GRANT ACCESS MANAGEMENT ON *.* TO user0")
|
||||
node.query("SET DEFAULT ROLE role0 TO CURRENT_USER", settings = [("user","user0")])
|
||||
|
||||
finally:
|
||||
with Finally("I drop the roles and users"):
|
||||
for i in range(2):
|
||||
node.query(f"DROP ROLE IF EXISTS role{i}")
|
||||
node.query(f"DROP USER IF EXISTS user{i}")
|
91
tests/testflows/rbac/tests/syntax/set_role.py
Executable file
91
tests/testflows/rbac/tests/syntax/set_role.py
Executable file
@ -0,0 +1,91 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("set role")
|
||||
@Args(format_description=False)
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check set role query syntax.
|
||||
|
||||
```
|
||||
SET ROLE {DEFAULT | NONE | role [,...] | ALL | ALL EXCEPT role [,...]}
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(roles=0):
|
||||
try:
|
||||
with Given("I have some roles"):
|
||||
for i in range(roles):
|
||||
node.query(f"CREATE ROLE role{i}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the roles"):
|
||||
for i in range(roles):
|
||||
node.query(f"DROP ROLE IF EXISTS role{i}")
|
||||
|
||||
with Scenario("I set default role for current user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetRole_Default("1.0")]):
|
||||
with When("I set default role for current user"):
|
||||
node.query("SET ROLE DEFAULT")
|
||||
|
||||
with Scenario("I set no role for current user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetRole_None("1.0")]):
|
||||
with When("I set no role for current user"):
|
||||
node.query("SET ROLE NONE")
|
||||
|
||||
with Scenario("I set nonexistent role, throws exception", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetRole_None("1.0")]):
|
||||
with Given("I ensure that role role5 does not exist"):
|
||||
node.query("DROP ROLE IF EXISTS role5")
|
||||
with When("I set nonexistent role for current user"):
|
||||
exitcode, message = errors.role_not_found_in_disk("role5")
|
||||
node.query("SET ROLE role5", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I set nonexistent role, throws exception", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetRole_None("1.0")]):
|
||||
with Given("I ensure that role role5 does not exist"):
|
||||
node.query("DROP ROLE IF EXISTS role5")
|
||||
with When("I set nonexistent role for current user"):
|
||||
exitcode, message = errors.role_not_found_in_disk("role5")
|
||||
node.query("SET ROLE ALL EXCEPT role5", exitcode=exitcode, message=message)
|
||||
|
||||
with Scenario("I set one role for current user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetRole("1.0")]):
|
||||
with setup(1):
|
||||
with Given("I have a user"):
|
||||
node.query("CREATE USER OR REPLACE user0")
|
||||
with And("I grant user a role"):
|
||||
node.query("GRANT role0 TO user0")
|
||||
with When("I set role for the user"):
|
||||
node.query("SET ROLE role0", settings = [("user","user0")])
|
||||
with Finally("I drop the user"):
|
||||
node.query("DROP USER user0")
|
||||
|
||||
with Scenario("I set multiple roles for current user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetRole("1.0")]):
|
||||
with setup(2):
|
||||
with Given("I have a user"):
|
||||
node.query("CREATE USER OR REPLACE user0")
|
||||
with And("I grant user a role"):
|
||||
node.query("GRANT role0, role1 TO user0")
|
||||
with When("I set roles for the user"):
|
||||
node.query("SET ROLE role0, role1", settings = [("user","user0")])
|
||||
with Finally("I drop the user"):
|
||||
node.query("DROP USER user0")
|
||||
|
||||
with Scenario("I set all roles for current user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetRole_All("1.0")]):
|
||||
with When("I set all roles for current user"):
|
||||
node.query("SET ROLE ALL")
|
||||
|
||||
with Scenario("I set all roles except one for current user", flags = TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SetRole_AllExcept("1.0")]):
|
||||
with setup(1):
|
||||
with When("I run set role command"):
|
||||
node.query("SET ROLE ALL EXCEPT role0")
|
44
tests/testflows/rbac/tests/syntax/show_create_quota.py
Executable file
44
tests/testflows/rbac/tests/syntax/show_create_quota.py
Executable file
@ -0,0 +1,44 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
|
||||
@TestFeature
|
||||
@Name("show create quota")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check show create quota query syntax.
|
||||
|
||||
```sql
|
||||
SHOW CREATE QUOTA [name | CURRENT]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(quota):
|
||||
try:
|
||||
with Given("I have a quota"):
|
||||
node.query(f"CREATE QUOTA {quota}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the quota"):
|
||||
node.query(f"DROP QUOTA IF EXISTS {quota}")
|
||||
|
||||
with Scenario("I show create quota", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Name("1.0")]):
|
||||
with cleanup("quota0"):
|
||||
with When("I run show create quota command"):
|
||||
node.query("SHOW CREATE QUOTA quota0")
|
||||
|
||||
with Scenario("I show create quota current", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Current("1.0")]):
|
||||
with cleanup("quota1"):
|
||||
with When("I run show create quota command"):
|
||||
node.query("SHOW CREATE QUOTA CURRENT")
|
||||
|
||||
with Scenario("I show create quota current short form", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_ShowCreateQuota_Current("1.0")]):
|
||||
with cleanup("quota2"):
|
||||
with When("I run show create quota command"):
|
||||
node.query("SHOW CREATE QUOTA")
|
39
tests/testflows/rbac/tests/syntax/show_create_role.py
Executable file
39
tests/testflows/rbac/tests/syntax/show_create_role.py
Executable file
@ -0,0 +1,39 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
import rbac.tests.errors as errors
|
||||
|
||||
@TestFeature
|
||||
@Name("show create role")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check show create role query syntax.
|
||||
|
||||
```sql
|
||||
SHOW CREATE ROLE name
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(role):
|
||||
try:
|
||||
with Given("I have a role"):
|
||||
node.query(f"CREATE ROLE OR REPLACE {role}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the role"):
|
||||
node.query(f"DROP ROLE IF EXISTS {role}")
|
||||
|
||||
with Scenario("I show create role", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_ShowCreate("1.0")]):
|
||||
with setup("role0"):
|
||||
with When("I run show create role command"):
|
||||
node.query("SHOW CREATE ROLE role0")
|
||||
|
||||
with Scenario("I show create role, role doesn't exist, exception", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Role_ShowCreate("1.0")]):
|
||||
with When("I run show create role to catch an exception"):
|
||||
exitcode, message = errors.role_not_found_in_disk(name="role0")
|
||||
node.query("SHOW CREATE ROLE role0", exitcode=exitcode, message=message)
|
51
tests/testflows/rbac/tests/syntax/show_create_row_policy.py
Executable file
51
tests/testflows/rbac/tests/syntax/show_create_row_policy.py
Executable file
@ -0,0 +1,51 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
|
||||
@TestFeature
|
||||
@Name("show create row policy")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check show create row policy query syntax.
|
||||
|
||||
```sql
|
||||
SHOW CREATE [ROW] POLICY name ON [database.]table
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(policy, on="default.foo"):
|
||||
try:
|
||||
with Given("I have a row policy"):
|
||||
node.query(f"CREATE ROW POLICY {policy} ON {on}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the row policy"):
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {policy} ON {on}")
|
||||
|
||||
try:
|
||||
with Given("I have a table"):
|
||||
node.query(f"CREATE TABLE default.foo (x UInt64, y String) Engine=Memory")
|
||||
|
||||
with Scenario("I show create row policy", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy("1.0")]):
|
||||
with cleanup("policy0"):
|
||||
with When("I run show create row policy command"):
|
||||
node.query("SHOW CREATE ROW POLICY policy0 ON default.foo")
|
||||
|
||||
with Scenario("I show create row policy on a table", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_On("1.0")]):
|
||||
with cleanup("policy0"):
|
||||
with When("I run show create row policy command"):
|
||||
node.query("SHOW CREATE ROW POLICY policy0 ON default.foo")
|
||||
|
||||
with Scenario("I show create row policy using short syntax on a table", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_ShowCreateRowPolicy_On("1.0")]):
|
||||
with cleanup("policy1",on="foo"):
|
||||
with When("I run show create row policy command"):
|
||||
node.query("SHOW CREATE POLICY policy1 ON foo")
|
||||
finally:
|
||||
with Finally("I drop the table"):
|
||||
node.query(f"DROP TABLE IF EXISTS default.foo")
|
38
tests/testflows/rbac/tests/syntax/show_create_settings_profile.py
Executable file
38
tests/testflows/rbac/tests/syntax/show_create_settings_profile.py
Executable file
@ -0,0 +1,38 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
|
||||
@TestFeature
|
||||
@Name("show create settings profile")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check show create settings profile query syntax.
|
||||
|
||||
```sql
|
||||
SHOW CREATE [SETTINGS] PROFILE name
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(profile):
|
||||
try:
|
||||
with Given("I have a settings profile"):
|
||||
node.query(f"CREATE SETTINGS PROFILE {profile}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the settings profile"):
|
||||
node.query(f"DROP SETTINGS PROFILE IF EXISTS {profile}")
|
||||
|
||||
with Scenario("I show create settings profile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_ShowCreateSettingsProfile("1.0")]):
|
||||
with cleanup("profile0"):
|
||||
with When("I run show create settings profile command"):
|
||||
node.query("SHOW CREATE SETTINGS PROFILE profile0")
|
||||
|
||||
with Scenario("I show create settings profile short form", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_SettingsProfile_ShowCreateSettingsProfile("1.0")]):
|
||||
with cleanup("profile1"):
|
||||
with When("I run show create settings profile command"):
|
||||
node.query("SHOW CREATE PROFILE profile1")
|
37
tests/testflows/rbac/tests/syntax/show_create_user.py
Executable file
37
tests/testflows/rbac/tests/syntax/show_create_user.py
Executable file
@ -0,0 +1,37 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
|
||||
@TestFeature
|
||||
@Name("show create user")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check show create user query syntax.
|
||||
|
||||
```
|
||||
SHOW CREATE USER [name | CURRENT_USER]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(user):
|
||||
try:
|
||||
with Given("I have a user"):
|
||||
node.query(f"CREATE USER {user}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the user"):
|
||||
node.query(f"DROP USER IF EXISTS {user}")
|
||||
|
||||
with Scenario("I run show create on user with no options", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_ShowCreateUser_For("1.0")]):
|
||||
with setup("user0"):
|
||||
with When("I run show create user command"):
|
||||
node.query("SHOW CREATE USER user0")
|
||||
|
||||
with Scenario("I run show create on current user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_User_ShowCreateUser("1.0")]):
|
||||
with When("I show create the current user"):
|
||||
node.query("SHOW CREATE USER CURRENT_USER")
|
37
tests/testflows/rbac/tests/syntax/show_grants.py
Executable file
37
tests/testflows/rbac/tests/syntax/show_grants.py
Executable file
@ -0,0 +1,37 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
|
||||
@TestFeature
|
||||
@Name("show grants")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check show grants query syntax.
|
||||
|
||||
```sql
|
||||
SHOW GRANTS [FOR user_or_role]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def setup(user):
|
||||
try:
|
||||
with Given("I have a user"):
|
||||
node.query(f"CREATE USER {user}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the user"):
|
||||
node.query(f"DROP USER IF EXISTS {user}")
|
||||
|
||||
with Scenario("I show grants for user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Show_Grants_For("1.0")]):
|
||||
with setup("user0"):
|
||||
with When("I run show grants command"):
|
||||
node.query("SHOW GRANTS FOR user0")
|
||||
|
||||
with Scenario("I show grants for current user", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Show_Grants("1.0")]):
|
||||
with When("I show grants"):
|
||||
node.query("SHOW GRANTS")
|
50
tests/testflows/rbac/tests/syntax/show_quotas.py
Executable file
50
tests/testflows/rbac/tests/syntax/show_quotas.py
Executable file
@ -0,0 +1,50 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
|
||||
@TestFeature
|
||||
@Name("show quotas")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check show quotas query syntax.
|
||||
|
||||
```sql
|
||||
SHOW QUOTAS
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(quota):
|
||||
try:
|
||||
with Given("I have a quota"):
|
||||
node.query(f"CREATE QUOTA OR REPLACE {quota}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the quota"):
|
||||
node.query(f"DROP QUOTA IF EXISTS {quota}")
|
||||
|
||||
with Scenario("I show quotas", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_ShowQuotas("1.0")]):
|
||||
with cleanup("quota0"), cleanup("quota1"):
|
||||
with When("I run show quota command"):
|
||||
node.query("SHOW QUOTAS")
|
||||
|
||||
with Scenario("I show quotas into outfile", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_ShowQuotas_IntoOutfile("1.0")]):
|
||||
with cleanup("quota0"), cleanup("quota1"):
|
||||
with When("I run show quota command"):
|
||||
node.query("SHOW QUOTAS INTO OUTFILE 'quotas.txt'")
|
||||
|
||||
with Scenario("I show quotas with format", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_ShowQuotas_Format("1.0")]):
|
||||
with cleanup("quota0"), cleanup("quota1"):
|
||||
with When("I run show quota command"):
|
||||
node.query("SHOW QUOTAS FORMAT TabSeparated")
|
||||
|
||||
with Scenario("I show quotas with settings", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_Quota_ShowQuotas("1.0")]):
|
||||
with cleanup("quota0"), cleanup("quota1"):
|
||||
with When("I run show quota command"):
|
||||
node.query("SHOW QUOTAS SETTINGS max_memory_usage=5")
|
58
tests/testflows/rbac/tests/syntax/show_row_policies.py
Executable file
58
tests/testflows/rbac/tests/syntax/show_row_policies.py
Executable file
@ -0,0 +1,58 @@
|
||||
from contextlib import contextmanager
|
||||
|
||||
from testflows.core import *
|
||||
|
||||
from rbac.requirements import *
|
||||
|
||||
@TestFeature
|
||||
@Name("show row policies")
|
||||
def feature(self, node="clickhouse1"):
|
||||
"""Check show row polices query syntax.
|
||||
|
||||
```sql
|
||||
SHOW [ROW] POLICIES [ON [database.]table]
|
||||
```
|
||||
"""
|
||||
node = self.context.cluster.node(node)
|
||||
|
||||
@contextmanager
|
||||
def cleanup(policy, on="default.foo"):
|
||||
try:
|
||||
with Given("I have a row policy"):
|
||||
node.query(f"CREATE ROW POLICY {policy} ON {on}")
|
||||
yield
|
||||
finally:
|
||||
with Finally("I drop the row policy"):
|
||||
node.query(f"DROP ROW POLICY IF EXISTS {policy} ON {on}")
|
||||
|
||||
try:
|
||||
with Given("I have a table"):
|
||||
node.query(f"CREATE TABLE default.foo (x UInt64, y String) Engine=Memory")
|
||||
|
||||
with Scenario("I show row policies", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies("1.0")]):
|
||||
with cleanup("policy0"):
|
||||
with When("I run drop row policy command"):
|
||||
node.query("SHOW ROW POLICIES")
|
||||
|
||||
with Scenario("I show row policies using short syntax", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies("1.0")]):
|
||||
with cleanup("policy1"):
|
||||
with When("I run drop row policy command"):
|
||||
node.query("SHOW POLICIES")
|
||||
|
||||
with Scenario("I show row policies on a database table", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_On("1.0")]):
|
||||
with cleanup("policy0"):
|
||||
with When("I run drop row policy command"):
|
||||
node.query("SHOW ROW POLICIES ON default.foo")
|
||||
|
||||
with Scenario("I show row policies on a table", flags=TE, requirements=[
|
||||
RQ_SRS_006_RBAC_RowPolicy_ShowRowPolicies_On("1.0")]):
|
||||
with cleanup("policy0"):
|
||||
with When("I run drop row policy command"):
|
||||
node.query("SHOW ROW POLICIES ON foo")
|
||||
|
||||
finally:
|
||||
with Finally("I drop the table"):
|
||||
node.query(f"DROP TABLE IF EXISTS default.foo")
|
Loading…
Reference in New Issue
Block a user