Skip to content
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
7 changes: 7 additions & 0 deletions src/server/server_family.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ ABSL_DECLARE_FLAG(string, tls_ca_cert_file);
ABSL_DECLARE_FLAG(string, tls_ca_cert_dir);
ABSL_DECLARE_FLAG(int, replica_priority);
ABSL_DECLARE_FLAG(double, rss_oom_deny_ratio);
ABSL_DECLARE_FLAG(uint32_t, memcached_port);

bool AbslParseFlag(std::string_view in, ReplicaOfFlag* flag, std::string* err) {
#define RETURN_ON_ERROR(cond, m) \
Expand Down Expand Up @@ -299,6 +300,12 @@ bool ValidateServerTlsFlags() {
has_auth = true;
}

// Allow TLS without authentication for memcached protocol
// We check if memcached_port is enabled, as this is a static check during startup
if (GetFlag(FLAGS_memcached_port) > 0) {
has_auth = true;
}

if (!has_auth) {
LOG(ERROR) << "TLS configured but no authentication method is used!";
return false;
Expand Down
39 changes: 39 additions & 0 deletions tests/dragonfly/pymemcached_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import socket
import random
import time
import ssl

from . import dfly_args
from .instance import DflyInstance
Expand Down Expand Up @@ -171,3 +172,41 @@ def test_expiration(memcached_client: MCClient):
assert memcached_client.get("key1") == None
assert memcached_client.get("key2") == None
assert memcached_client.get("key3") == None


@dfly_args(DEFAULT_ARGS)
def test_memcached_tls_no_requirepass(df_factory, with_tls_server_args, with_tls_ca_cert_args):
"""
Test for issue #5084: ability to use TLS for Memcached without requirepass.

Dragonfly required a password to be set when using TLS, but the Memcached protocol
does not support password authentication. This test verifies that we can start
the server with TLS enabled but without specifying requirepass and with the Memcached port.
"""
# Create arguments for TLS without specifying requirepass
server_args = {**DEFAULT_ARGS, **with_tls_server_args}

# Create and start the server - it should not crash
server = df_factory.create(**server_args)
server.start()

# Give the server time to start
time.sleep(1)

# Create SSL context for client
ssl_context = ssl.create_default_context()
ssl_context.load_verify_locations(with_tls_ca_cert_args["ca_cert"])
ssl_context.check_hostname = False

# Disable certificate verification (since we don't provide a client certificate)
ssl_context.verify_mode = ssl.CERT_NONE

# Output port information for diagnostics
print(f"Connecting to memcached port: {server.mc_port} on host: 127.0.0.1")
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: we do not use prints in tests - only logging.info/debug etc


# Connect to Memcached over TLS
client = MCClient(("127.0.0.1", server.mc_port), tls_context=ssl_context)

# Test basic operations
assert client.set("foo", "bar")
assert client.get("foo") == b"bar"