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

Add password authentication to Redis ports #2952

Merged
merged 27 commits into from
Oct 17, 2018

Conversation

pschafhalter
Copy link
Contributor

What do these changes do?

  • Adds password authentication to Redis ports via ray.init(redis_password="my_password")
  • Throws exception if redis_password is set, but Raylet is not running
  • Adds a test to verify that Redis ports are secure

Related issue number

#2925
#2457

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8341/
Test PASSed.

@AmplabJenkins
Copy link

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8343/
Test FAILed.

python/ray/test/test_ray_init.py Show resolved Hide resolved
@@ -1315,6 +1365,7 @@ def start_ray_processes(address_info=None,
num_redis_shards=1,
redis_max_clients=None,
redis_protected_mode=False,
redis_password=None,
Copy link
Collaborator

Choose a reason for hiding this comment

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

We probably want to remove all instances of the redis_protected_mode/protected_mode argument, right? And also essentially remove everything from #2697, right (e.g., the code for making the temp file and stuff)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I was planning to do that in a follow-up PR so I don't change too much at once. If you think it's more appropriate, I'll clean up redis_protected_mode in this PR.

Copy link
Collaborator

Choose a reason for hiding this comment

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

A follow up PR is fine.

@@ -135,7 +135,30 @@ RedisContext::~RedisContext() {
}
}

Status RedisContext::Connect(const std::string &address, int port, bool sharding) {
static std::string default_password = "";
Copy link
Collaborator

Choose a reason for hiding this comment

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

This appears in multiple places. Consider moving it to https://github.com/ray-project/ray/blob/master/src/ray/constants.h.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8361/
Test PASSed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8525/
Test PASSed.

@pschafhalter pschafhalter changed the title Add password authentication to Redis ports [WIP] Add password authentication to Redis ports Oct 3, 2018
@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8593/
Test PASSed.

@pschafhalter pschafhalter changed the title [WIP] Add password authentication to Redis ports Add password authentication to Redis ports Oct 12, 2018
@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8606/
Test PASSed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8670/
Test PASSed.

-----------------------------

Ray instances should run on a secure network without public facing ports.
The most common threat for Ray instances is unautherized access to Redis,
Copy link
Collaborator

Choose a reason for hiding this comment

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

typo "unauthorized"

password = "some_password"
exception = None

# Fix for #3045
Copy link
Collaborator

Choose a reason for hiding this comment

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

Include the full URL

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually, I don't think we need to make a global variable, in generally we should be doing less in the fixture and more in the actual test. Why not move everything to the actual tests and just leave something like

ray/test/runtest.py

Lines 205 to 209 in 6240ccb

@pytest.fixture
def shutdown_only():
yield None
# The code after the yield will run as teardown code.
ray.shutdown()

in the fixture?


@pytest.fixture
def start_ray_with_password():
ray.shutdown()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are we calling ray.shutdown at the start of the fixture? We don't do this in any of our other tests.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead, our fixtures usually do something like

ray.init()

yield None

ray.shutdown()

try:
info = ray.init(redis_password=password)
except Exception as e:
info = ray.init(redis_password=None)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is the purpose of this codepath?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I intended to test that an exception is thrown when passing a redis_password without using raylet, although I can do this instead:

ray/test/runtest.py

Lines 2165 to 2167 in 6240ccb

@pytest.mark.skipif(
os.environ.get("RAY_USE_NEW_GCS") == "on",
reason="New GCS API doesn't have a Python API yet.")

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I'd just skip the test entirely in the non-raylet case. If you want to include a test for the non-raylet case then I'd just make it a separate test.



@pytest.fixture
def use_credis():
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can also just use

ray/test/runtest.py

Lines 2165 to 2167 in 6240ccb

@pytest.mark.skipif(
os.environ.get("RAY_USE_NEW_GCS") == "on",
reason="New GCS API doesn't have a Python API yet.")

def test_raylet_only(self, start_ray_with_password, use_credis):
password, info, exception, use_raylet = start_ray_with_password
if use_raylet and not use_credis:
assert exception is None
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's natural to just run the test and if it raises an exception, then pytest will report the error. Instead, we're catching the exception and then asserting that the exception is not None, which is very roundabout.



class TestRedisPassword(object):
def test_raylet_only(self, start_ray_with_password, use_credis):
Copy link
Collaborator

Choose a reason for hiding this comment

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

These tests can probably all be combined into one.

@@ -135,7 +135,30 @@ RedisContext::~RedisContext() {
}
}

Status RedisContext::Connect(const std::string &address, int port, bool sharding) {
Status authenticate_redis(redisContext *context, const std::string &password) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

These functions don't follow the naming convention I think. @pcmoritz can comment, but I think it should be AuthenticateRedis.

# Check that we can run a task
task_id = f.remote()
ready, running = ray.wait([task_id], timeout=5000)
assert len(ready) > 0, "Expected task to complete"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Kind of a nit, but task_id should be object_id.

Also, instead of doing wait followed by an assert, maybe just do ray.get(object_id).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mind if I keep the ray.wait? While testing, I ran into a case where ray.get wouldn't fail, but block indefinitely (I think this was when I discovered the issues with the new GCS).

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8672/
Test PASSed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8673/
Test PASSed.

@AmplabJenkins
Copy link

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8676/
Test FAILed.

@robertnishihara
Copy link
Collaborator

@pschafhalter looks good to me except there are linting errors. Could you fix those?

@AmplabJenkins
Copy link

Test FAILed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8680/
Test FAILed.

@AmplabJenkins
Copy link

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins//job/Ray-PRB/8681/
Test PASSed.

@pcmoritz pcmoritz merged commit a41bbc1 into ray-project:master Oct 17, 2018
@pschafhalter pschafhalter deleted the redis-password branch October 17, 2018 07:21
robertnishihara pushed a commit that referenced this pull request Oct 18, 2018
Follow-up to #2925 and #2952. Removes the Redis protected mode implementation from Ray which was replaced by Redis port authentication.
@igorkost-ibm
Copy link

File python/ray/worker.py [line 2084]: redis_password wasn't passed to services.record_log_files_in_redis(...) function.
image

@pschafhalter
Copy link
Contributor Author

@igoriokas thanks! I'll fix this in a follow-up PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants