mirror of
https://github.com/wassname/ray.git
synced 2026-07-13 17:45:08 +08:00
Add password authentication to Redis ports (#2952)
* Implement Redis authentication * Throw exception for legacy Ray * Add test * Formatting * Fix bugs in CLI * Fix bugs in Raylet * Move default password to constants.h * Use pytest.fixture * Fix bug * Authenticate using formatted strings * Add missing passwords * Add test * Improve authentication of async contexts * Disable Redis authentication for credis * Update test for credis * Fix rebase artifacts * Fix formatting * Add workaround for issue #3045 * Increase timeout for test * Improve C++ readability * Fixes for CLI * Add security docs * Address comments * Address comments * Adress comments * Use ray.get * Fix lint
This commit is contained in:
committed by
Philipp Moritz
parent
a9e454f6fd
commit
a41bbc10ef
+19
-11
@@ -71,10 +71,12 @@ namespace gcs {
|
||||
|
||||
AsyncGcsClient::AsyncGcsClient(const std::string &address, int port,
|
||||
const ClientID &client_id, CommandType command_type,
|
||||
bool is_test_client = false) {
|
||||
bool is_test_client = false,
|
||||
const std::string &password = "") {
|
||||
primary_context_ = std::make_shared<RedisContext>();
|
||||
|
||||
RAY_CHECK_OK(primary_context_->Connect(address, port, /*sharding=*/true));
|
||||
RAY_CHECK_OK(
|
||||
primary_context_->Connect(address, port, /*sharding=*/true, /*password=*/password));
|
||||
|
||||
if (!is_test_client) {
|
||||
// Moving sharding into constructor defaultly means that sharding = true.
|
||||
@@ -94,12 +96,13 @@ AsyncGcsClient::AsyncGcsClient(const std::string &address, int port,
|
||||
|
||||
RAY_CHECK(shard_contexts_.size() == addresses.size());
|
||||
for (size_t i = 0; i < addresses.size(); ++i) {
|
||||
RAY_CHECK_OK(
|
||||
shard_contexts_[i]->Connect(addresses[i], ports[i], /*sharding=*/true));
|
||||
RAY_CHECK_OK(shard_contexts_[i]->Connect(addresses[i], ports[i], /*sharding=*/true,
|
||||
/*password=*/password));
|
||||
}
|
||||
} else {
|
||||
shard_contexts_.push_back(std::make_shared<RedisContext>());
|
||||
RAY_CHECK_OK(shard_contexts_[0]->Connect(address, port, /*sharding=*/true));
|
||||
RAY_CHECK_OK(shard_contexts_[0]->Connect(address, port, /*sharding=*/true,
|
||||
/*password=*/password));
|
||||
}
|
||||
|
||||
client_table_.reset(new ClientTable({primary_context_}, this, client_id));
|
||||
@@ -126,12 +129,16 @@ AsyncGcsClient::AsyncGcsClient(const std::string &address, int port,
|
||||
// Use of kChain currently only applies to Table::Add which affects only the
|
||||
// task table, and when RAY_USE_NEW_GCS is set at compile time.
|
||||
AsyncGcsClient::AsyncGcsClient(const std::string &address, int port,
|
||||
const ClientID &client_id, bool is_test_client = false)
|
||||
: AsyncGcsClient(address, port, client_id, CommandType::kChain, is_test_client) {}
|
||||
const ClientID &client_id, bool is_test_client = false,
|
||||
const std::string &password = "")
|
||||
: AsyncGcsClient(address, port, client_id, CommandType::kChain, is_test_client,
|
||||
password) {}
|
||||
#else
|
||||
AsyncGcsClient::AsyncGcsClient(const std::string &address, int port,
|
||||
const ClientID &client_id, bool is_test_client = false)
|
||||
: AsyncGcsClient(address, port, client_id, CommandType::kRegular, is_test_client) {}
|
||||
const ClientID &client_id, bool is_test_client = false,
|
||||
const std::string &password = "")
|
||||
: AsyncGcsClient(address, port, client_id, CommandType::kRegular, is_test_client,
|
||||
password) {}
|
||||
#endif // RAY_USE_NEW_GCS
|
||||
|
||||
AsyncGcsClient::AsyncGcsClient(const std::string &address, int port,
|
||||
@@ -143,8 +150,9 @@ AsyncGcsClient::AsyncGcsClient(const std::string &address, int port,
|
||||
: AsyncGcsClient(address, port, ClientID::from_random(), command_type,
|
||||
is_test_client) {}
|
||||
|
||||
AsyncGcsClient::AsyncGcsClient(const std::string &address, int port)
|
||||
: AsyncGcsClient(address, port, ClientID::from_random()) {}
|
||||
AsyncGcsClient::AsyncGcsClient(const std::string &address, int port,
|
||||
const std::string &password = "")
|
||||
: AsyncGcsClient(address, port, ClientID::from_random(), false, password) {}
|
||||
|
||||
AsyncGcsClient::AsyncGcsClient(const std::string &address, int port, bool is_test_client)
|
||||
: AsyncGcsClient(address, port, ClientID::from_random(), is_test_client) {}
|
||||
|
||||
@@ -31,13 +31,14 @@ class RAY_EXPORT AsyncGcsClient {
|
||||
/// \param command_type GCS command type. If CommandType::kChain, chain-replicated
|
||||
/// versions of the tables might be used, if available.
|
||||
AsyncGcsClient(const std::string &address, int port, const ClientID &client_id,
|
||||
CommandType command_type, bool is_test_client);
|
||||
CommandType command_type, bool is_test_client,
|
||||
const std::string &redis_password);
|
||||
AsyncGcsClient(const std::string &address, int port, const ClientID &client_id,
|
||||
bool is_test_client);
|
||||
bool is_test_client, const std::string &password);
|
||||
AsyncGcsClient(const std::string &address, int port, CommandType command_type);
|
||||
AsyncGcsClient(const std::string &address, int port, CommandType command_type,
|
||||
bool is_test_client);
|
||||
AsyncGcsClient(const std::string &address, int port);
|
||||
AsyncGcsClient(const std::string &address, int port, const std::string &password);
|
||||
AsyncGcsClient(const std::string &address, int port, bool is_test_client);
|
||||
|
||||
/// Attach this client to a plasma event loop. Note that only
|
||||
|
||||
@@ -135,7 +135,30 @@ RedisContext::~RedisContext() {
|
||||
}
|
||||
}
|
||||
|
||||
Status RedisContext::Connect(const std::string &address, int port, bool sharding) {
|
||||
Status AuthenticateRedis(redisContext *context, const std::string &password) {
|
||||
if (password == "") {
|
||||
return Status::OK();
|
||||
}
|
||||
redisReply *reply =
|
||||
reinterpret_cast<redisReply *>(redisCommand(context, "AUTH %s", password.c_str()));
|
||||
REDIS_CHECK_ERROR(context, reply);
|
||||
freeReplyObject(reply);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AuthenticateRedis(redisAsyncContext *context, const std::string &password) {
|
||||
if (password == "") {
|
||||
return Status::OK();
|
||||
}
|
||||
int status = redisAsyncCommand(context, NULL, NULL, "AUTH %s", password.c_str());
|
||||
if (status == REDIS_ERR) {
|
||||
return Status::RedisError(std::string(context->errstr));
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status RedisContext::Connect(const std::string &address, int port, bool sharding,
|
||||
const std::string &password = "") {
|
||||
int connection_attempts = 0;
|
||||
context_ = redisConnect(address.c_str(), port);
|
||||
while (context_ == nullptr || context_->err) {
|
||||
@@ -155,6 +178,8 @@ Status RedisContext::Connect(const std::string &address, int port, bool sharding
|
||||
context_ = redisConnect(address.c_str(), port);
|
||||
connection_attempts += 1;
|
||||
}
|
||||
RAY_CHECK_OK(AuthenticateRedis(context_, password));
|
||||
|
||||
redisReply *reply = reinterpret_cast<redisReply *>(
|
||||
redisCommand(context_, "CONFIG SET notify-keyspace-events Kl"));
|
||||
REDIS_CHECK_ERROR(context_, reply);
|
||||
@@ -166,12 +191,16 @@ Status RedisContext::Connect(const std::string &address, int port, bool sharding
|
||||
RAY_LOG(FATAL) << "Could not establish connection to redis " << address << ":"
|
||||
<< port;
|
||||
}
|
||||
RAY_CHECK_OK(AuthenticateRedis(async_context_, password));
|
||||
|
||||
// Connect to subscribe context
|
||||
subscribe_context_ = redisAsyncConnect(address.c_str(), port);
|
||||
if (subscribe_context_ == nullptr || subscribe_context_->err) {
|
||||
RAY_LOG(FATAL) << "Could not establish subscribe connection to redis " << address
|
||||
<< ":" << port;
|
||||
}
|
||||
RAY_CHECK_OK(AuthenticateRedis(subscribe_context_, password));
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ class RedisContext {
|
||||
RedisContext()
|
||||
: context_(nullptr), async_context_(nullptr), subscribe_context_(nullptr) {}
|
||||
~RedisContext();
|
||||
Status Connect(const std::string &address, int port, bool sharding);
|
||||
Status Connect(const std::string &address, int port, bool sharding,
|
||||
const std::string &password);
|
||||
Status AttachToEventLoop(aeEventLoop *loop);
|
||||
|
||||
/// Run an operation on some table key.
|
||||
|
||||
@@ -19,7 +19,7 @@ int main(int argc, char *argv[]) {
|
||||
ray::RayLog::ShutDownRayLog, argv[0], RAY_INFO,
|
||||
/*log_dir=*/"");
|
||||
ray::RayLog::InstallFailureSignalHandler();
|
||||
RAY_CHECK(argc == 11);
|
||||
RAY_CHECK(argc == 11 || argc == 12);
|
||||
|
||||
const std::string raylet_socket_name = std::string(argv[1]);
|
||||
const std::string store_socket_name = std::string(argv[2]);
|
||||
@@ -31,6 +31,7 @@ int main(int argc, char *argv[]) {
|
||||
const std::string static_resource_list = std::string(argv[8]);
|
||||
const std::string python_worker_command = std::string(argv[9]);
|
||||
const std::string java_worker_command = std::string(argv[10]);
|
||||
const std::string redis_password = (argc == 12 ? std::string(argv[11]) : "");
|
||||
|
||||
// Configuration for the node manager.
|
||||
ray::raylet::NodeManagerConfig node_manager_config;
|
||||
@@ -92,7 +93,8 @@ int main(int argc, char *argv[]) {
|
||||
<< "object_chunk_size = " << object_manager_config.object_chunk_size;
|
||||
|
||||
// initialize mock gcs & object directory
|
||||
auto gcs_client = std::make_shared<ray::gcs::AsyncGcsClient>(redis_address, redis_port);
|
||||
auto gcs_client = std::make_shared<ray::gcs::AsyncGcsClient>(redis_address, redis_port,
|
||||
redis_password);
|
||||
RAY_LOG(DEBUG) << "Initializing GCS client "
|
||||
<< gcs_client->client_table().GetLocalClientId();
|
||||
|
||||
@@ -100,8 +102,8 @@ int main(int argc, char *argv[]) {
|
||||
boost::asio::io_service main_service;
|
||||
|
||||
ray::raylet::Raylet server(main_service, raylet_socket_name, node_ip_address,
|
||||
redis_address, redis_port, node_manager_config,
|
||||
object_manager_config, gcs_client);
|
||||
redis_address, redis_port, redis_password,
|
||||
node_manager_config, object_manager_config, gcs_client);
|
||||
|
||||
// Destroy the Raylet on a SIGTERM. The pointer to main_service is
|
||||
// guaranteed to be valid since this function will run the event loop
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace raylet {
|
||||
/// the Ray configuration), then the monitor will mark that Raylet as dead in
|
||||
/// the client table, which broadcasts the event to all other Raylets.
|
||||
Monitor::Monitor(boost::asio::io_service &io_service, const std::string &redis_address,
|
||||
int redis_port)
|
||||
: gcs_client_(redis_address, redis_port),
|
||||
int redis_port, const std::string &redis_password)
|
||||
: gcs_client_(redis_address, redis_port, redis_password),
|
||||
num_heartbeats_timeout_(RayConfig::instance().num_heartbeats_timeout()),
|
||||
heartbeat_timer_(io_service) {
|
||||
RAY_CHECK_OK(gcs_client_.Attach(io_service));
|
||||
|
||||
@@ -19,7 +19,7 @@ class Monitor {
|
||||
/// \param redis_address The GCS Redis address to connect to.
|
||||
/// \param redis_port The GCS Redis port to connect to.
|
||||
Monitor(boost::asio::io_service &io_service, const std::string &redis_address,
|
||||
int redis_port);
|
||||
int redis_port, const std::string &redis_password);
|
||||
|
||||
/// Start the monitor. Listen for heartbeats from Raylets and mark Raylets
|
||||
/// that do not send a heartbeat within a given period as dead.
|
||||
|
||||
@@ -8,14 +8,15 @@ int main(int argc, char *argv[]) {
|
||||
ray::RayLog::ShutDownRayLog, argv[0], RAY_INFO,
|
||||
/*log_dir=*/"");
|
||||
ray::RayLog::InstallFailureSignalHandler();
|
||||
RAY_CHECK(argc == 3);
|
||||
RAY_CHECK(argc == 3 || argc == 4);
|
||||
|
||||
const std::string redis_address = std::string(argv[1]);
|
||||
int redis_port = std::stoi(argv[2]);
|
||||
const std::string redis_password = (argc == 4 ? std::string(argv[3]) : "");
|
||||
|
||||
// Initialize the monitor.
|
||||
boost::asio::io_service io_service;
|
||||
ray::raylet::Monitor monitor(io_service, redis_address, redis_port);
|
||||
ray::raylet::Monitor monitor(io_service, redis_address, redis_port, redis_password);
|
||||
monitor.Start();
|
||||
io_service.run();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class TestObjectManagerBase : public ::testing::Test {
|
||||
om_config_1.store_socket_name = store_sock_1;
|
||||
om_config_1.push_timeout_ms = 10000;
|
||||
server1.reset(new ray::raylet::Raylet(
|
||||
main_service, "raylet_1", "0.0.0.0", "127.0.0.1", 6379,
|
||||
main_service, "raylet_1", "0.0.0.0", "127.0.0.1", 6379, "",
|
||||
GetNodeManagerConfig("raylet_1", store_sock_1), om_config_1, gcs_client_1));
|
||||
|
||||
// start second server
|
||||
@@ -70,7 +70,7 @@ class TestObjectManagerBase : public ::testing::Test {
|
||||
om_config_2.store_socket_name = store_sock_2;
|
||||
om_config_2.push_timeout_ms = 10000;
|
||||
server2.reset(new ray::raylet::Raylet(
|
||||
main_service, "raylet_2", "0.0.0.0", "127.0.0.1", 6379,
|
||||
main_service, "raylet_2", "0.0.0.0", "127.0.0.1", 6379, "",
|
||||
GetNodeManagerConfig("raylet_2", store_sock_2), om_config_2, gcs_client_2));
|
||||
|
||||
// connect to stores.
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace raylet {
|
||||
|
||||
Raylet::Raylet(boost::asio::io_service &main_service, const std::string &socket_name,
|
||||
const std::string &node_ip_address, const std::string &redis_address,
|
||||
int redis_port, const NodeManagerConfig &node_manager_config,
|
||||
int redis_port, const std::string &redis_password,
|
||||
const NodeManagerConfig &node_manager_config,
|
||||
const ObjectManagerConfig &object_manager_config,
|
||||
std::shared_ptr<gcs::AsyncGcsClient> gcs_client)
|
||||
: gcs_client_(gcs_client),
|
||||
@@ -33,9 +34,9 @@ Raylet::Raylet(boost::asio::io_service &main_service, const std::string &socket_
|
||||
DoAcceptObjectManager();
|
||||
DoAcceptNodeManager();
|
||||
|
||||
RAY_CHECK_OK(RegisterGcs(node_ip_address, socket_name_,
|
||||
object_manager_config.store_socket_name, redis_address,
|
||||
redis_port, main_service, node_manager_config));
|
||||
RAY_CHECK_OK(RegisterGcs(
|
||||
node_ip_address, socket_name_, object_manager_config.store_socket_name,
|
||||
redis_address, redis_port, redis_password, main_service, node_manager_config));
|
||||
|
||||
RAY_CHECK_OK(RegisterPeriodicTimer(main_service));
|
||||
}
|
||||
@@ -52,6 +53,7 @@ ray::Status Raylet::RegisterGcs(const std::string &node_ip_address,
|
||||
const std::string &raylet_socket_name,
|
||||
const std::string &object_store_socket_name,
|
||||
const std::string &redis_address, int redis_port,
|
||||
const std::string &redis_password,
|
||||
boost::asio::io_service &io_service,
|
||||
const NodeManagerConfig &node_manager_config) {
|
||||
RAY_RETURN_NOT_OK(gcs_client_->Attach(io_service));
|
||||
|
||||
@@ -29,6 +29,7 @@ class Raylet {
|
||||
/// \param node_ip_address The IP address of this node.
|
||||
/// \param redis_address The IP address of the redis instance we are connecting to.
|
||||
/// \param redis_port The port of the redis instance we are connecting to.
|
||||
/// \param redis_password The password of the redis instance we are connecting to.
|
||||
/// \param node_manager_config Configuration to initialize the node manager.
|
||||
/// scheduler with.
|
||||
/// \param object_manager_config Configuration to initialize the object
|
||||
@@ -36,7 +37,8 @@ class Raylet {
|
||||
/// \param gcs_client A client connection to the GCS.
|
||||
Raylet(boost::asio::io_service &main_service, const std::string &socket_name,
|
||||
const std::string &node_ip_address, const std::string &redis_address,
|
||||
int redis_port, const NodeManagerConfig &node_manager_config,
|
||||
int redis_port, const std::string &redis_password,
|
||||
const NodeManagerConfig &node_manager_config,
|
||||
const ObjectManagerConfig &object_manager_config,
|
||||
std::shared_ptr<gcs::AsyncGcsClient> gcs_client);
|
||||
|
||||
@@ -49,6 +51,7 @@ class Raylet {
|
||||
const std::string &raylet_socket_name,
|
||||
const std::string &object_store_socket_name,
|
||||
const std::string &redis_address, int redis_port,
|
||||
const std::string &redis_password,
|
||||
boost::asio::io_service &io_service, const NodeManagerConfig &);
|
||||
|
||||
ray::Status RegisterPeriodicTimer(boost::asio::io_service &io_service);
|
||||
|
||||
Reference in New Issue
Block a user