-
Notifications
You must be signed in to change notification settings - Fork 6.8k
[Core] Add authentication token logic and related tests #58046
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
base: master
Are you sure you want to change the base?
Conversation
Signed-off-by: sampan <[email protected]>
Bug: Whitespace Handling Causes Undefined BehaviorThe |
Bug: Environment Variables Reference Invalid MemoryOn Windows, Additional Locations (1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces token-based authentication for Ray Core RPCs, which is a great security enhancement. The changes include a secure AuthenticationToken class, a loader for tokens from various sources, and related configuration. The implementation is well-structured and includes comprehensive tests.
I've found a critical issue in the test suite on Windows related to environment variable handling that needs to be addressed. I've also left a few other comments for improving code style, efficiency, and robustness. Overall, this is a solid contribution.
| void set_env_var(const char *name, const char *value) { | ||
| #ifdef _WIN32 | ||
| std::string env_str = std::string(name) + "=" + std::string(value); | ||
| _putenv(env_str.c_str()); | ||
| #else | ||
| setenv(name, value, 1); | ||
| #endif | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Windows implementation of set_env_var has a critical bug. The _putenv function does not copy the string it's given; it only stores the pointer. Here, env_str is a local variable, so the pointer passed to _putenv becomes dangling as soon as this function returns, leading to undefined behavior.
The same issue exists in unset_env_var (lines 119-126) and SetUp (lines 52-64) for the _putenv call.
To fix this, the string buffer must remain valid for the duration of its use in the environment. A good approach for this test class would be to store these environment strings in a std::vector<std::string> member of the AuthenticationTokenLoaderTest fixture.
Example fix for set_env_var:
- Add
std::vector<std::string> managed_env_strings_;to the test fixture. - Modify
set_env_varlike this:
#ifdef _WIN32
managed_env_strings_.emplace_back(std::string(name) + "=" + std::string(value));
_putenv(managed_env_strings_.back().c_str());
#else
setenv(name, value, 1);
#endifYou'll need to apply similar fixes to unset_env_var and SetUp.
| const std::string_view prefix(kBearerPrefix, sizeof(kBearerPrefix) - 1); | ||
| if (metadata_value.size() <= prefix.size() || | ||
| metadata_value.substr(0, prefix.size()) != prefix) { | ||
| return AuthenticationToken(); // Invalid format, return empty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation for stripping the "Bearer " prefix can be made more robust and readable. Using sizeof(kBearerPrefix) - 1 is a C-style idiom that can be brittle if the constant definition changes. A more modern C++ approach using std::string_view's properties would be safer. Also, the size check can be simplified for better clarity.
| const std::string_view prefix(kBearerPrefix, sizeof(kBearerPrefix) - 1); | |
| if (metadata_value.size() <= prefix.size() || | |
| metadata_value.substr(0, prefix.size()) != prefix) { | |
| return AuthenticationToken(); // Invalid format, return empty | |
| const std::string_view prefix(kBearerPrefix); | |
| if (metadata_value.size() < prefix.size() || | |
| metadata_value.substr(0, prefix.size()) != prefix) { | |
| return AuthenticationToken(); // Invalid format, return empty | |
| } |
| #if defined(__APPLE__) || defined(__linux__) | ||
| #include <sys/stat.h> | ||
| #include <unistd.h> | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| AuthenticationToken AuthenticationTokenLoader::LoadTokenFromSources() { | ||
| // Precedence 1: RAY_AUTH_TOKEN environment variable | ||
| const char *env_token = std::getenv("RAY_AUTH_TOKEN"); | ||
| if (env_token != nullptr && std::string(env_token).length() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a std::string from a const char* just to check its length is inefficient as it can cause a memory allocation. You can check if the C-style string is non-empty more efficiently.
| if (env_token != nullptr && std::string(env_token).length() > 0) { | |
| if (env_token != nullptr && *env_token != '\0') { |
|
|
||
| // Precedence 2: RAY_AUTH_TOKEN_PATH environment variable | ||
| const char *env_token_path = std::getenv("RAY_AUTH_TOKEN_PATH"); | ||
| if (env_token_path != nullptr && std::string(env_token_path).length() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a std::string from a const char* just to check its length is inefficient as it can cause a memory allocation. You can check if the C-style string is non-empty more efficiently.
| if (env_token_path != nullptr && std::string(env_token_path).length() > 0) { | |
| if (env_token_path != nullptr && *env_token_path != '\0') { |
| std::string get_temp_token_path() { | ||
| #ifdef _WIN32 | ||
| return "C:\\Windows\\Temp\\ray_test_token_" + std::to_string(_getpid()); | ||
| #else | ||
| return "/tmp/ray_test_token_" + std::to_string(getpid()); | ||
| #endif | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoding temporary paths like /tmp/ and C:\\Windows\\Temp\\ can make tests brittle, as the user running them may not have write permissions. It's better to use a standard temporary directory. You're already using TEST_TMPDIR in SetUp, which is a good practice to follow here as well. Using . as a fallback on Windows is safer than C:\\Windows\\Temp.
std::string get_temp_token_path() {
const char *tmp_dir_from_env = std::getenv("TEST_TMPDIR");
#ifdef _WIN32
const char *tmp_dir = tmp_dir_from_env ? tmp_dir_from_env : ".";
return std::string(tmp_dir) + "\\ray_test_token_" + std::to_string(_getpid());
#else
const char *tmp_dir = tmp_dir_from_env ? tmp_dir_from_env : "/tmp";
return std::string(tmp_dir) + "/ray_test_token_" + std::to_string(getpid());
#endif
}Signed-off-by: sampan <[email protected]>
Signed-off-by: sampan <[email protected]>
Bug: Whitespace Handling Bug in
|
Description
this pr sets up the helper classes and utils to enable token based authentication for ray core rpc calls.
Related issues
NA
Additional information