add setting allow_ddl

This commit is contained in:
CurtizJ 2018-09-11 21:37:19 +03:00
parent 94183c7af1
commit c1ed0bb86a
7 changed files with 43 additions and 18 deletions

View File

@ -55,6 +55,7 @@ namespace ErrorCodes
extern const int DUPLICATE_COLUMN;
extern const int READONLY;
extern const int ILLEGAL_COLUMN;
extern const int QUERY_IS_PROHIBITED;
}
@ -634,23 +635,26 @@ void InterpreterCreateQuery::checkAccess(const ASTCreateQuery & create)
const Settings & settings = context.getSettingsRef();
auto readonly = settings.readonly;
auto allow_ddl = settings.allow_ddl;
if (!readonly)
{
if (!readonly && allow_ddl)
return;
}
/// CREATE|ATTACH DATABASE
if (!create.database.empty() && create.table.empty())
{
throw Exception("Cannot create database in readonly mode", ErrorCodes::READONLY);
if (readonly)
throw Exception("Cannot create database in readonly mode", ErrorCodes::READONLY);
throw Exception("Cannot create database. DDL queries are prohibited for the user", ErrorCodes::QUERY_IS_PROHIBITED);
}
if (create.is_temporary && readonly >= 2)
{
return;
}
throw Exception("Cannot create table in readonly mode", ErrorCodes::READONLY);
if (readonly)
throw Exception("Cannot create table in readonly mode", ErrorCodes::READONLY);
throw Exception("Cannot create table. DDL queries are prohibited for the user", ErrorCodes::QUERY_IS_PROHIBITED);
}
}

View File

@ -22,6 +22,7 @@ namespace ErrorCodes
extern const int LOGICAL_ERROR;
extern const int SYNTAX_ERROR;
extern const int UNKNOWN_TABLE;
extern const int QUERY_IS_PROHIBITED;
}
@ -217,14 +218,16 @@ void InterpreterDropQuery::checkAccess(const ASTDropQuery & drop)
{
const Settings & settings = context.getSettingsRef();
auto readonly = settings.readonly;
bool allow_ddl = settings.allow_ddl;
/// It's allowed to drop temporary tables.
if (!readonly || (drop.database.empty() && context.tryGetExternalTable(drop.table) && readonly >= 2))
{
if ((!readonly && allow_ddl) || (drop.database.empty() && context.tryGetExternalTable(drop.table) && readonly >= 2))
return;
}
throw Exception("Cannot drop table in readonly mode", ErrorCodes::READONLY);
if (readonly)
throw Exception("Cannot drop table in readonly mode", ErrorCodes::READONLY);
throw Exception("Cannot drop table. DDL queries are prohibited for the user", ErrorCodes::QUERY_IS_PROHIBITED);
}
}

View File

@ -54,10 +54,11 @@ namespace ErrorCodes
{
extern const int READONLY;
extern const int UNKNOWN_TYPE_OF_QUERY;
extern const int QUERY_IS_PROHIBITED;
}
static void throwIfReadOnly(Context & context)
static void throwIfNoAccess(Context & context)
{
if (context.getSettingsRef().readonly)
{
@ -68,6 +69,8 @@ static void throwIfReadOnly(Context & context)
else
throw Exception("Cannot execute query in readonly mode", ErrorCodes::READONLY);
}
else if (!context.getSettingsRef().allow_ddl)
throw Exception("Cannot execute query. DDL queries are prohibited for the user", ErrorCodes::QUERY_IS_PROHIBITED);
}
@ -95,17 +98,17 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, Context &
}
else if (typeid_cast<ASTCreateQuery *>(query.get()))
{
/// readonly is checked inside InterpreterCreateQuery
/// readonly and allow_ddl are checked inside InterpreterCreateQuery
return std::make_unique<InterpreterCreateQuery>(query, context);
}
else if (typeid_cast<ASTDropQuery *>(query.get()))
{
/// readonly is checked inside InterpreterDropQuery
/// readonly and allow_ddl are checked inside InterpreterDropQuery
return std::make_unique<InterpreterDropQuery>(query, context);
}
else if (typeid_cast<ASTRenameQuery *>(query.get()))
{
throwIfReadOnly(context);
throwIfNoAccess(context);
return std::make_unique<InterpreterRenameQuery>(query, context);
}
else if (typeid_cast<ASTShowTablesQuery *>(query.get()))
@ -123,7 +126,7 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, Context &
}
else if (typeid_cast<ASTOptimizeQuery *>(query.get()))
{
throwIfReadOnly(context);
throwIfNoAccess(context);
return std::make_unique<InterpreterOptimizeQuery>(query, context);
}
else if (typeid_cast<ASTExistsQuery *>(query.get()))
@ -148,7 +151,7 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, Context &
}
else if (typeid_cast<ASTAlterQuery *>(query.get()))
{
throwIfReadOnly(context);
throwIfNoAccess(context);
return std::make_unique<InterpreterAlterQuery>(query, context);
}
else if (typeid_cast<ASTCheckQuery *>(query.get()))
@ -161,7 +164,7 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, Context &
}
else if (typeid_cast<ASTSystemQuery *>(query.get()))
{
throwIfReadOnly(context);
throwIfNoAccess(context);
return std::make_unique<InterpreterSystemQuery>(query, context);
}
else

View File

@ -10,6 +10,7 @@ namespace DB
namespace ErrorCodes
{
extern const int READONLY;
extern const int QUERY_IS_PROHIBITED;
}
@ -36,6 +37,7 @@ void InterpreterSetQuery::checkAccess(const ASTSetQuery & ast)
const Settings & settings = context.getSettingsRef();
auto readonly = settings.readonly;
auto allow_ddl = settings.allow_ddl;
for (const auto & change : ast.changes)
{
@ -43,6 +45,10 @@ void InterpreterSetQuery::checkAccess(const ASTSetQuery & ast)
/// Setting isn't checked if value wasn't changed.
if (!settings.tryGet(change.name, value) || applyVisitor(FieldVisitorToString(), change.value) != value)
{
if (!allow_ddl && change.name == "allow_ddl")
throw Exception("Cannot modify 'allow_ddl' setting when DDL queries are not allowed", ErrorCodes::QUERY_IS_PROHIBITED);
if (readonly == 1)
throw Exception("Cannot execute SET query in readonly mode", ErrorCodes::READONLY);

View File

@ -288,6 +288,7 @@ struct Settings
M(SettingBool, asterisk_left_columns_only, 0, "If it is set to true, the asterisk only return left of join query.") \
M(SettingUInt64, http_max_multipart_form_data_size, 1024 * 1024 * 1024, "Limit on size of multipart/form-data content. This setting cannot be parsed from URL parameters and should be set in user profile. Note that content is parsed and external tables are created in memory before start of query execution. And this is the only limit that has effect on that stage (limits on max memory usage and max execution time have no effect while reading HTTP form data).") \
M(SettingBool, calculate_text_stack_trace, 1, "Calculate text stack trace in case of exceptions during query execution. This is the default. It requires symbol lookups that may slow down fuzzing tests when huge amount of wrong queries are executed. In normal cases you should not disable this option.") \
M(SettingBool, allow_ddl, true, "If it is set to true, then a user is allowed to executed DDL queries.") \
#define DECLARE(TYPE, NAME, DEFAULT, DESCRIPTION) \

View File

@ -0,0 +1,8 @@
SET send_logs_level = 'none';
SET allow_ddl = 0;
CREATE DATABASE some_db; -- { serverError 392 }
CREATE TABLE test.some_table(a Int32) ENGINE = Memory; -- { serverError 392}
ALTER TABLE test.some_table DELETE WHERE 1; -- { serverError 392}
RENAME TABLE test.some_table TO test.some_table1; -- { serverError 392}
SET allow_ddl = 1; -- { serverError 392}