Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User permission manager #1873

Merged
merged 5 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions etc/nebula-graphd.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@
--default_charset=utf8
# The defaule collate when a space is created
--default_collate=utf8_bin

########## authorization ##########
# Enable authorization
--enable_authorize=false
4 changes: 4 additions & 0 deletions etc/nebula-graphd.conf.production
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@
--ws_h2_port=13002

--heartbeat_interval_secs=10

########## authorization ##########
# Enable authorization
--enable_authorize=false
2 changes: 2 additions & 0 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ nebula_add_subdirectory(test)
nebula_add_subdirectory(charset)
nebula_add_subdirectory(algorithm)
nebula_add_subdirectory(encryption)
nebula_add_subdirectory(permission)
nebula_add_subdirectory(session)

3 changes: 3 additions & 0 deletions src/common/base/Status.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ std::string Status::toString() const {
case kSyntaxError:
str = "SyntaxError: ";
break;
case kPermissionError:
str = "PermissionError: ";
break;
default:
snprintf(tmp, sizeof(tmp), "Unknown error(%hu): ", static_cast<uint16_t>(code()));
str = tmp;
Expand Down
4 changes: 4 additions & 0 deletions src/common/permission/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nebula_add_library(
permission_obj OBJECT
PermissionManager.cpp
)
223 changes: 223 additions & 0 deletions src/common/permission/PermissionManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#include "permission/PermissionManager.h"

namespace nebula {
namespace permission {

// static
bool PermissionManager::canReadSpace(session::Session *session, GraphSpaceID spaceId) {
if (!FLAGS_enable_authorize) {
return true;
}
if (session->isGod()) {
return true;
}
bool havePermission = false;
switch (session->roleWithSpace(spaceId)) {
case session::Role::GOD :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between session->isGod() and session::Role::GOD ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between session->isGod() and session::Role::GOD ?

session->isGod just check if the user is god.
session->roleWithSpace(spaceId) check what role of in this space.
case session::Role::GOD still there because the compilation requirement of switch block .

case session::Role::ADMIN :
case session::Role::DBA :
case session::Role::USER :
case session::Role::GUEST : {
havePermission = true;
break;
}
case session::Role::INVALID_ROLE : {
break;
}
}
return havePermission;
}

// static
bool PermissionManager::canReadSchemaOrData(session::Session *session) {
if (session->space() == -1) {
LOG(ERROR) << "The space name is not set";
return false;
}
if (session->isGod()) {
return true;
}
bool havePermission = false;
switch (session->roleWithSpace(session->space())) {
case session::Role::GOD :
case session::Role::ADMIN :
case session::Role::DBA :
case session::Role::USER :
case session::Role::GUEST : {
havePermission = true;
break;
}
case session::Role::INVALID_ROLE : {
break;
}
}
return havePermission;
}

// static
bool PermissionManager::canWriteSpace(session::Session *session) {
return session->isGod();
}

// static
bool PermissionManager::canWriteSchema(session::Session *session) {
if (session->space() == -1) {
LOG(ERROR) << "The space name is not set";
return false;
}
if (session->isGod()) {
return true;
}
bool havePermission = false;
switch (session->roleWithSpace(session->space())) {
case session::Role::GOD :
case session::Role::ADMIN :
case session::Role::DBA : {
havePermission = true;
break;
}
case session::Role::USER :
case session::Role::GUEST :
case session::Role::INVALID_ROLE : {
break;
}
}
return havePermission;
}

// static
bool PermissionManager::canWriteUser(session::Session *session) {
return session->isGod();
}

bool PermissionManager::canWriteRole(session::Session *session,
session::Role targetRole,
GraphSpaceID spaceId,
const std::string& targetUser) {
if (!FLAGS_enable_authorize) {
return true;
}
/**
* Reject grant or revoke to himself.
*/
if (session->user() == targetUser) {
return false;
}
/*
* Reject any user grant or revoke role to GOD
*/
if (targetRole == session::Role::GOD) {
return false;
}
/*
* God user can be grant or revoke any one.
*/
if (session->isGod()) {
return true;
}
/**
* Only allow ADMIN user grant or revoke other user to DBA, USER, GUEST.
*/
auto role = session->roleWithSpace(spaceId);
if (role == session::Role::ADMIN && targetRole != session::Role::ADMIN) {
return true;
}
return false;
}

// static
bool PermissionManager::canWriteData(session::Session *session) {
if (session->space() == -1) {
bright-starry-sky marked this conversation as resolved.
Show resolved Hide resolved
LOG(ERROR) << "The space name is not set";
return false;
}
if (session->isGod()) {
return true;
}
bool havePermission = false;
switch (session->roleWithSpace(session->space())) {
case session::Role::GOD :
case session::Role::ADMIN :
case session::Role::DBA :
case session::Role::USER : {
havePermission = true;
break;
}
case session::Role::GUEST :
case session::Role::INVALID_ROLE : {
break;
}
}
return havePermission;
}

// static
bool PermissionManager::canShow(session::Session *session,
ShowSentence::ShowType type,
GraphSpaceID targetSpace) {
if (!FLAGS_enable_authorize) {
return true;
}
bool havePermission = false;
switch (type) {
case ShowSentence::ShowType::kShowParts:
case ShowSentence::ShowType::kShowTags:
case ShowSentence::ShowType::kShowEdges:
case ShowSentence::ShowType::kShowTagIndexes:
case ShowSentence::ShowType::kShowEdgeIndexes:
case ShowSentence::ShowType::kShowCreateTag:
case ShowSentence::ShowType::kShowCreateEdge:
case ShowSentence::ShowType::kShowCreateTagIndex:
case ShowSentence::ShowType::kShowCreateEdgeIndex:
case ShowSentence::ShowType::kShowTagIndexStatus:
case ShowSentence::ShowType::kShowEdgeIndexStatus: {
/**
* Above operations can get the space id via session,
* so the permission same with canReadSchemaOrData.
* They've been checked by "USE SPACE", so here skip the check.
*/
havePermission = true;
break;
}
case ShowSentence::ShowType::kShowCharset:
case ShowSentence::ShowType::kShowCollation:
case ShowSentence::ShowType::kShowHosts: {
/**
* all roles can be show for above operations.
*/
havePermission = true;
break;
}
case ShowSentence::ShowType::kShowSpaces:
case ShowSentence::ShowType::kShowCreateSpace:
case ShowSentence::ShowType::kShowRoles: {
/*
* Above operations are special operation.
* can not get the space id via session,
* Permission checking needs to be done in their executor.
*/
havePermission = canReadSpace(session, targetSpace);
break;
}
case ShowSentence::ShowType::kShowUsers:
case ShowSentence::ShowType::kShowSnapshots: {
/**
* Only GOD role can be show.
*/
havePermission = session->isGod();
break;
}
case ShowSentence::ShowType::kUnknown:
break;
}
return havePermission;
}

} // namespace permission
} // namespace nebula
42 changes: 42 additions & 0 deletions src/common/permission/PermissionManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#ifndef COMMON_PERMISSION_PERMISSIONMANAGER_H_
#define COMMON_PERMISSION_PERMISSIONMANAGER_H_

#include "base/Base.h"
#include "session/Session.h"
#include "meta/client/MetaClient.h"
#include "parser/Sentence.h"
#include "parser/UserSentences.h"
#include "parser/AdminSentences.h"
#include "graph/GraphFlags.h"

namespace nebula {
namespace permission {

class PermissionManager final {
public:
PermissionManager() = delete;
static bool canReadSpace(session::Session *session, GraphSpaceID spaceId);
static bool canReadSchemaOrData(session::Session *session);
static bool canWriteSpace(session::Session *session);
static bool canWriteSchema(session::Session *session);
static bool canWriteUser(session::Session *session);
static bool canWriteRole(session::Session *session,
session::Role targetRole,
GraphSpaceID spaceId,
const std::string& targetUser);
static bool canWriteData(session::Session *session);
static bool canShow(session::Session *session,
ShowSentence::ShowType type,
GraphSpaceID targetSpace = -1);
};
} // namespace permission
} // namespace nebula

#endif // COMMON_PERMISSION_PERMISSIONMANAGER_H_

4 changes: 4 additions & 0 deletions src/common/session/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nebula_add_library(
session_obj OBJECT
Session.cpp
)
28 changes: 28 additions & 0 deletions src/common/session/Session.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#include "session/Session.h"

namespace nebula {
namespace session {

Session::Session(int64_t id) {
id_ = id;
}

std::shared_ptr<Session> Session::create(int64_t id) {
return std::shared_ptr<Session>(new Session(id));
}

void Session::charge() {
idleDuration_.reset();
}

uint64_t Session::idleSeconds() const {
return idleDuration_.elapsedInSec();
}
} // namespace session
} // namespace nebula
Loading