diff --git a/docs/content/latest/secure/enable-authentication/ycql.md b/docs/content/latest/secure/enable-authentication/ycql.md index 96cb27114ad1..dba2bf2b374e 100644 --- a/docs/content/latest/secure/enable-authentication/ycql.md +++ b/docs/content/latest/secure/enable-authentication/ycql.md @@ -273,7 +273,7 @@ Connecting to the cluster with the default password would no longer work: ``` $ bin/ycqlsh -u cassandra -p cassandra Connection error: - ... Provided username cassandra and/or password are incorrect ... + ... Provided username 'cassandra' and/or password are incorrect ... ``` You can now connect to the cluster using the new password: diff --git a/docs/content/stable/secure/enable-authentication/ycql.md b/docs/content/stable/secure/enable-authentication/ycql.md index c091e1e04c8c..9e8b49fa9d7e 100644 --- a/docs/content/stable/secure/enable-authentication/ycql.md +++ b/docs/content/stable/secure/enable-authentication/ycql.md @@ -273,7 +273,7 @@ Connecting to the cluster with the default password would no longer work: ``` $ bin/ycqlsh -u cassandra -p cassandra Connection error: - ... Provided username cassandra and/or password are incorrect ... + ... Provided username 'cassandra' and/or password are incorrect ... ``` You can now connect to the cluster using the new password: diff --git a/java/yb-cql/src/test/java/org/yb/cql/TestAudit.java b/java/yb-cql/src/test/java/org/yb/cql/TestAudit.java index d5784da498a5..56562315d299 100644 --- a/java/yb-cql/src/test/java/org/yb/cql/TestAudit.java +++ b/java/yb-cql/src/test/java/org/yb/cql/TestAudit.java @@ -111,7 +111,7 @@ public void auth() throws Exception { assertAudit( new AuditLogEntry('E', "null", "LOGIN_ERROR", "AUTH", null /* batchId */, null /* keyspace */, null /* scope */, - "LOGIN FAILURE; Provided username user1 and/or password are incorrect")); + "LOGIN FAILURE; Provided username 'user1' and/or password are incorrect")); } catch (Exception ex) { throw ex; } diff --git a/java/yb-cql/src/test/java/org/yb/cql/TestLDAPAuth.java b/java/yb-cql/src/test/java/org/yb/cql/TestLDAPAuth.java index 3dca4bacf6c1..565b79f69f6d 100644 --- a/java/yb-cql/src/test/java/org/yb/cql/TestLDAPAuth.java +++ b/java/yb-cql/src/test/java/org/yb/cql/TestLDAPAuth.java @@ -33,6 +33,7 @@ import org.yb.YBTestRunner; // TODO(Piyush): Test with TLS and LDAPS +// TODO(Piyush): Reduce test time by force updating gflags instead of restarting cluster @RunWith(value=YBTestRunner.class) @CreateDS(name = "myDS", @@ -40,7 +41,8 @@ @CreatePartition(name = "test", suffix = "dc=myorg,dc=com") }) @CreateLdapServer(transports = { - @CreateTransport(protocol = "LDAP", address = "localhost", port=10389)}) + @CreateTransport(protocol = "LDAP", address = "localhost", port=10389)}, + allowAnonymousAccess = true) // We allow this to test if YCQL still blocks such a bind @ApplyLdifs({ "dn: dc=myorg,dc=com", "objectClass: domain", @@ -93,6 +95,11 @@ public class TestLDAPAuth extends BaseAuthenticationCQLTest { @ClassRule public static CreateLdapServerRule serverRule = new CreateLdapServerRule(); + @Override + public int getTestMethodTimeoutSec() { + return 240; + } + private void recreateMiniCluster(Map extraTserverFlag) throws Exception { destroyMiniCluster(); Map tserverFlags = new HashMap<>(); @@ -121,6 +128,28 @@ public void incorrectLDAPServer() throws Exception { session.execute("DROP ROLE 'testUser1'"); } + void testUnauthenticatedAndAnonymousBinds() { + // Test Unauthenticated bind - non-empty username and empty password + // Refer: https://datatracker.ietf.org/doc/html/rfc4513#section-5.1.2 + checkConnectivityWithMessage(true, "testUser1", "", ProtocolOptions.Compression.NONE, + true /* expectFailure */, + "Empty username and/or password not allowed"); + + // In below cases, with empty user name, since the user doesn't exist in cassandra, we error out + // at an earlier stage and hence the error is different from the one for empty password. + + // Test Anonymous bind - empty username and empty password + // Refer: https://datatracker.ietf.org/doc/html/rfc4513#section-5.1.1 + checkConnectivityWithMessage(true, "", "", ProtocolOptions.Compression.NONE, + true /* expectFailure */, + "Provided username '' and/or password are incorrect"); + + // Extra case - empty username and non-empty password + checkConnectivityWithMessage(true, "", "12345", ProtocolOptions.Compression.NONE, + true /* expectFailure */, + "Provided username '' and/or password are incorrect"); + } + @Test public void simpleBindMode() throws Exception { // Test with incorrect user prefix @@ -132,9 +161,11 @@ public void simpleBindMode() throws Exception { checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, true /* expectFailure */, - "Failed to authenticate using LDAP: Provided username testUser1 and/or password are " + + "Failed to authenticate using LDAP: Provided username 'testUser1' and/or password are " + "incorrect"); + testUnauthenticatedAndAnonymousBinds(); + // Test with incorrect user suffix extraTserverFlagMap.clear(); extraTserverFlagMap.put("ycql_ldap_user_prefix", "cn="); @@ -144,9 +175,11 @@ public void simpleBindMode() throws Exception { checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, true /* expectFailure */, - "Failed to authenticate using LDAP: Provided username testUser1 and/or password are " + + "Failed to authenticate using LDAP: Provided username 'testUser1' and/or password are " + "incorrect"); + testUnauthenticatedAndAnonymousBinds(); + // Test with correct prefix and suffix extraTserverFlagMap.clear(); extraTserverFlagMap.put("ycql_ldap_user_prefix", "cn="); @@ -157,27 +190,24 @@ public void simpleBindMode() throws Exception { checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, false /* expectFailure */, ""); - // Incorrect username/password + // Incorrect password checkConnectivityWithMessage(true, "testUser1", "1234", ProtocolOptions.Compression.NONE, true /* expectFailure */, - "Failed to authenticate using LDAP: Provided username testUser1 and/or password are " + + "Failed to authenticate using LDAP: Provided username 'testUser1' and/or password are " + "incorrect"); + // Incorrect user - no role is created for testUser2 checkConnectivityWithMessage(true, "testUser2", "12345", ProtocolOptions.Compression.NONE, true /* expectFailure */, - "Provided username testUser2 and/or password are incorrect"); + "Provided username 'testUser2' and/or password are incorrect"); - checkConnectivityWithMessage(true, "testUser1", "", ProtocolOptions.Compression.NONE, - true /* expectFailure */, - "Failed to authenticate using LDAP: Internal error"); + testUnauthenticatedAndAnonymousBinds(); session.execute("DROP ROLE 'testUser1'"); } @Test - public void searchBindMode() throws Exception { - session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); - + public void searchBindModeWithSearchAttribute() throws Exception { // Test with incorrect bind user dn Map extraTserverFlagMap = getTServerFlags(); extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=dummy,ou=Users,dc=myorg,dc=com"); @@ -191,6 +221,8 @@ public void searchBindMode() throws Exception { true, /* expectFailure */ "could not perform initial LDAP bind for ldapbinddn 'cn=dummy,ou=Users,dc=myorg,dc=com'"); + testUnauthenticatedAndAnonymousBinds(); + // Test with incorrect bind password extraTserverFlagMap.clear(); extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); @@ -204,6 +236,8 @@ public void searchBindMode() throws Exception { true, /* expectFailure */ "could not perform initial LDAP bind for ldapbinddn 'cn=admin,ou=Users,dc=myorg,dc=com'"); + testUnauthenticatedAndAnonymousBinds(); + // Test with non-existant base dn extraTserverFlagMap.clear(); extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); @@ -219,7 +253,9 @@ public void searchBindMode() throws Exception { "'ldap://localhost:10389': No such object LDAP diagnostics: " + "NO_SUCH_OBJECT: failed for MessageType : SEARCH_REQUEST"); - // Test with incorrect incorrect search attribute + testUnauthenticatedAndAnonymousBinds(); + + // Test with incorrect search attribute extraTserverFlagMap.clear(); extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); extraTserverFlagMap.put("ycql_ldap_bind_passwd", "adminPasswd"); @@ -233,6 +269,8 @@ public void searchBindMode() throws Exception { "LDAP user 'testUser1' does not exist. LDAP search for filter '(dummy=testUser1)' on " + "server 'ldap://localhost:10389' returned no entries."); + testUnauthenticatedAndAnonymousBinds(); + // Test with all correct - bind db, bind password, base dn, search attribute extraTserverFlagMap.clear(); extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); @@ -245,17 +283,19 @@ public void searchBindMode() throws Exception { // Test with incorrect user checkConnectivityWithMessage(true, "dummy", "12345", ProtocolOptions.Compression.NONE, true, /* expectFailure */ - "Provided username dummy and/or password are incorrect"); + "Provided username 'dummy' and/or password are incorrect"); - // Test with incorrect user and password + // Test with incorrect password checkConnectivityWithMessage(true, "testUser1", "1234", ProtocolOptions.Compression.NONE, true, /* expectFailure */ - "Failed to authenticate using LDAP: Provided username testUser1 and/or " + + "Failed to authenticate using LDAP: Provided username 'testUser1' and/or " + "password are incorrect"); // Test with correct password checkConnectivity(true, "testUser1", "12345", false /* expectFailure */); + testUnauthenticatedAndAnonymousBinds(); + // Test with prefix of base dn extraTserverFlagMap.clear(); extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); @@ -268,17 +308,210 @@ public void searchBindMode() throws Exception { // Test with incorrect user checkConnectivityWithMessage(true, "dummy", "12345", ProtocolOptions.Compression.NONE, true, /* expectFailure */ - "Provided username dummy and/or password are incorrect"); + "Provided username 'dummy' and/or password are incorrect"); - // Test with incorrect user password + // Test with incorrect password checkConnectivityWithMessage(true, "testUser1", "1234", ProtocolOptions.Compression.NONE, true, /* expectFailure */ - "Failed to authenticate using LDAP: Provided username testUser1 and/or " + + "Failed to authenticate using LDAP: Provided username 'testUser1' and/or " + "password are incorrect"); // Test with correct password checkConnectivity(true, "testUser1", "12345", false /* expectFailure */); + testUnauthenticatedAndAnonymousBinds(); + + session.execute("CREATE ROLE 'test*User1' WITH LOGIN = true"); + // Test with user name that has characters that are not allowed + checkConnectivityWithMessage(true, "test*User1", "12345", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "invalid character in user name for LDAP authentication"); + + session.execute("CREATE ROLE 'testUserNonUnique' WITH LOGIN = true"); + // Test with more than one user name matching search criteria + checkConnectivityWithMessage(true, "testUserNonUnique", "12345", + ProtocolOptions.Compression.NONE, true, /* expectFailure */ + "LDAP user 'testUserNonUnique' is not unique, 2 entries exist."); + } + + @Test + public void searchBindModeWithEmptyConfigArgs() throws Exception { + // Test search+bind mode with empty arguments for - + // 1. ycql_ldap_bind_dn + // 2. ycql_ldap_bind_passwd + // 3. both ycql_ldap_bind_dn and ycql_ldap_bind_passwd empty + Map extraTserverFlagMap = getTServerFlags(); + + // Test with empty bind dn (all other flags have correct values) + extraTserverFlagMap.clear(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", ""); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", "adminPasswd"); + extraTserverFlagMap.put("ycql_ldap_base_dn", "ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_attribute", "cn"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + // Test with correct username and password + checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, + true /* expectFailure */, + "Empty bind dn and/or bind password not allowed for search+bind mode"); + + // Test with empty bind password (all other flags have correct values) + extraTserverFlagMap.clear(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", ""); + extraTserverFlagMap.put("ycql_ldap_base_dn", "ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_attribute", "cn"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, + true /* expectFailure */, + "Empty bind dn and/or bind password not allowed for search+bind mode"); + + // Test with both empty bind user dn and empty bind password (all other flags have correct + // values) + extraTserverFlagMap.clear(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", ""); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", ""); + extraTserverFlagMap.put("ycql_ldap_base_dn", "ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_attribute", "cn"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, + true /* expectFailure */, + "Empty bind dn and/or bind password not allowed for search+bind mode"); + } + + @Test + public void searchBindModeWithSearchFilter() throws Exception { + // Test with incorrect bind user dn + Map extraTserverFlagMap = getTServerFlags(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=dummy,ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", "adminPasswd"); + extraTserverFlagMap.put("ycql_ldap_base_dn", "ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_filter", "(cn=$username)"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "could not perform initial LDAP bind for ldapbinddn 'cn=dummy,ou=Users,dc=myorg,dc=com'"); + + testUnauthenticatedAndAnonymousBinds(); + + // Test with incorrect bind password + extraTserverFlagMap.clear(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", "dummyPasswd"); + extraTserverFlagMap.put("ycql_ldap_base_dn", "ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_filter", "(cn=$username)"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "could not perform initial LDAP bind for ldapbinddn 'cn=admin,ou=Users,dc=myorg,dc=com'"); + + testUnauthenticatedAndAnonymousBinds(); + + // Test with non-existant base dn + extraTserverFlagMap.clear(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", "adminPasswd"); + extraTserverFlagMap.put("ycql_ldap_base_dn", "ou=dummy,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_filter", "(cn=$username)"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "could not search LDAP for filter '(cn=testUser1)' on server " + + "'ldap://localhost:10389': No such object LDAP diagnostics: " + + "NO_SUCH_OBJECT: failed for MessageType : SEARCH_REQUEST"); + + testUnauthenticatedAndAnonymousBinds(); + + // Test with incorrect search filters + // Case 1: Incorrect tag instead of $username + extraTserverFlagMap.clear(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", "adminPasswd"); + extraTserverFlagMap.put("ycql_ldap_base_dn", "ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_filter", "(cn=$userna..)"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "LDAP user 'testUser1' does not exist. LDAP search for filter '(cn=$userna..)' on " + + "server 'ldap://localhost:10389' returned no entries."); + + testUnauthenticatedAndAnonymousBinds(); + + // Case 2: Incorrect attribute used, correct $username tag + extraTserverFlagMap.put("ycql_ldap_search_filter", "(dummy=$username)"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + checkConnectivityWithMessage(true, "testUser1", "12345", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "LDAP user 'testUser1' does not exist. LDAP search for filter '(dummy=testUser1)' on " + + "server 'ldap://localhost:10389' returned no entries."); + + testUnauthenticatedAndAnonymousBinds(); + + // Test with all correct - bind db, bind password, base dn, search filter + extraTserverFlagMap.clear(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", "adminPasswd"); + extraTserverFlagMap.put("ycql_ldap_base_dn", "ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_filter", "(cn=$username)"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + // Test with incorrect user + checkConnectivityWithMessage(true, "dummy", "12345", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "Provided username 'dummy' and/or password are incorrect"); + + // Test with incorrect password + checkConnectivityWithMessage(true, "testUser1", "1234", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "Failed to authenticate using LDAP: Provided username 'testUser1' and/or " + + "password are incorrect"); + + // Test with correct password + checkConnectivity(true, "testUser1", "12345", false /* expectFailure */); + + testUnauthenticatedAndAnonymousBinds(); + + // Test with prefix of base dn + extraTserverFlagMap.clear(); + extraTserverFlagMap.put("ycql_ldap_bind_dn", "cn=admin,ou=Users,dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_bind_passwd", "adminPasswd"); + extraTserverFlagMap.put("ycql_ldap_base_dn", "dc=myorg,dc=com"); + extraTserverFlagMap.put("ycql_ldap_search_filter", "(cn=$username)"); + recreateMiniCluster(extraTserverFlagMap); + session.execute("CREATE ROLE 'testUser1' WITH LOGIN = true"); + + // Test with incorrect user + checkConnectivityWithMessage(true, "dummy", "12345", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "Provided username 'dummy' and/or password are incorrect"); + + // Test with incorrect password + checkConnectivityWithMessage(true, "testUser1", "1234", ProtocolOptions.Compression.NONE, + true, /* expectFailure */ + "Failed to authenticate using LDAP: Provided username 'testUser1' and/or " + + "password are incorrect"); + + // Test with correct password + checkConnectivity(true, "testUser1", "12345", false /* expectFailure */); + + testUnauthenticatedAndAnonymousBinds(); + session.execute("CREATE ROLE 'test*User1' WITH LOGIN = true"); // Test with user name that has characters that are not allowed checkConnectivityWithMessage(true, "test*User1", "12345", ProtocolOptions.Compression.NONE, diff --git a/src/yb/yql/cql/cqlserver/cql_processor.cc b/src/yb/yql/cql/cqlserver/cql_processor.cc index 9ebdf341920d..52768e15814a 100644 --- a/src/yb/yql/cql/cqlserver/cql_processor.cc +++ b/src/yb/yql/cql/cqlserver/cql_processor.cc @@ -17,6 +17,8 @@ #include +#include + #include "yb/common/ql_value.h" #include "yb/gutil/strings/escaping.h" @@ -678,17 +680,38 @@ Result InitializeLDAPConnection(const char *uris) { return ldap; } +/* + * Return a newly allocated string copied from "pattern" with all + * occurrences of the placeholder "$username" replaced with "user_name". + */ +std::string FormatSearchFilter(const std::string& pattern, const std::string& user_name) { + return boost::replace_all_copy(pattern, "$username", user_name); +} + Result CheckLDAPAuth(const ql::AuthResponseRequest::AuthQueryParameters& params) { - VLOG(4) << "Attempting ldap_initialize() with " << FLAGS_ycql_ldap_server; + if (params.username.empty() || params.password.empty()) { + // Refer https://datatracker.ietf.org/doc/html/rfc4513#section-6.3.1 for details. Applications + // are required to explicitly have this check and can't rely on an LDAP server to report + // invalid credentials error. + return STATUS(InvalidArgument, "Empty username and/or password not allowed"); + } + if (FLAGS_ycql_ldap_server.empty()) return STATUS(InvalidArgument, "LDAP server not specified"); + VLOG(4) << "Attempting ldap_initialize() with " << FLAGS_ycql_ldap_server; + const auto& uris = FLAGS_ycql_ldap_server; auto ldap = VERIFY_RESULT(InitializeLDAPConnection(uris.c_str())); int r; std::string fulluser; if (!FLAGS_ycql_ldap_base_dn.empty()) { + if (FLAGS_ycql_ldap_bind_dn.empty() || FLAGS_ycql_ldap_bind_passwd.empty()) { + return STATUS(InvalidArgument, + "Empty bind dn and/or bind password not allowed for search+bind mode"); + } + /* * First perform an LDAP search to find the DN for the user we are * trying to log in as. @@ -733,10 +756,9 @@ Result CheckLDAPAuth(const ql::AuthResponseRequest::AuthQueryParameters& p std::string filter; /* Build a custom filter or a single attribute filter? */ - // TODO(Piyush): Support the search filter mode - // if (FLAGS_ycql_ldap_search_filter) - // filter = FormatSearchFilter(FLAGS_ycql_ldap_search_filter, params.username); - if (!FLAGS_ycql_ldap_search_attribute.empty()) { + if (!FLAGS_ycql_ldap_search_filter.empty()) { + filter = FormatSearchFilter(FLAGS_ycql_ldap_search_filter, params.username); + } else if (!FLAGS_ycql_ldap_search_attribute.empty()) { filter = "(" + FLAGS_ycql_ldap_search_attribute + "=" + params.username + ")"; } else { filter = "(uid=" + params.username + ")"; @@ -854,8 +876,8 @@ unique_ptr CQLProcessor::ProcessAuthResult(const string& saved_hash } else if (!*ldap_auth_result) { response = make_unique( *request_, ErrorResponse::Code::BAD_CREDENTIALS, - "Failed to authenticate using LDAP: Provided username " + params.username + - " and/or password are incorrect"); + "Failed to authenticate using LDAP: Provided username '" + params.username + + "' and/or password are incorrect"); } else { authenticated = true; call_->ql_session()->set_current_role_name(params.username); @@ -866,12 +888,12 @@ unique_ptr CQLProcessor::ProcessAuthResult(const string& saved_hash // Username doesn't have a password, but one is required for authentication. Return an error. response = make_unique( *request_, ErrorResponse::Code::BAD_CREDENTIALS, - "Provided username " + params.username + " and/or password are incorrect"); + "Provided username '" + params.username + "' and/or password are incorrect"); } else { if (!service_impl_->CheckPassword(params.password, saved_hash)) { response = make_unique( *request_, ErrorResponse::Code::BAD_CREDENTIALS, - "Provided username " + params.username + " and/or password are incorrect"); + "Provided username '" + params.username + "' and/or password are incorrect"); } else if (!can_login) { response = make_unique( *request_, ErrorResponse::Code::BAD_CREDENTIALS, @@ -919,7 +941,7 @@ unique_ptr CQLProcessor::ProcessResult(const ExecutedResult::Shared if (row_block->row_count() != 1) { response = make_unique( *request_, ErrorResponse::Code::BAD_CREDENTIALS, - "Provided username " + params.username + " and/or password are incorrect"); + "Provided username '" + params.username + "' and/or password are incorrect"); } else { const auto& row = row_block->row(0); const auto& schema = row_block->schema(); diff --git a/src/yb/yql/cql/cqlserver/cqlserver-test.cc b/src/yb/yql/cql/cqlserver/cqlserver-test.cc index 9ca896f1cf03..dbc604221d4d 100644 --- a/src/yb/yql/cql/cqlserver/cqlserver-test.cc +++ b/src/yb/yql/cql/cqlserver/cqlserver-test.cc @@ -501,18 +501,18 @@ TEST_F(TestCQLServiceWithCassAuth, TestReadSystemTableAuthenticated) { "\x00\x00\x00\x17" // body size "\x00\x00\x00\x13" "\x00" "acssandra" "\x00" "password"), BINARY_STRING("\x84\x00\x00\x00\x00" // 0x00 = ERROR - "\x00\x00\x00\x3f" // body size + "\x00\x00\x00\x41" // body size "\x00\x00\x01\x00" // error code - "\x00\x39" "Provided username acssandra and/or password are incorrect")); + "\x00\x3b" "Provided username 'acssandra' and/or password are incorrect")); // Invalid authorization: send wrong password. SendRequestAndExpectResponse( BINARY_STRING("\x04\x00\x00\x00\x0f" // 0x0F = AUTH_RESPONSE "\x00\x00\x00\x17" // body size "\x00\x00\x00\x13" "\x00" "cassandra" "\x00" "password"), BINARY_STRING("\x84\x00\x00\x00\x00" // 0x00 = ERROR - "\x00\x00\x00\x3f" // body size + "\x00\x00\x00\x41" // body size "\x00\x00\x01\x00" // error code - "\x00\x39" "Provided username cassandra and/or password are incorrect")); + "\x00\x3b" "Provided username 'cassandra' and/or password are incorrect")); // Invalid authorization: send null token. SendRequestAndExpectResponse( BINARY_STRING("\x04\x00\x00\x00\x0f" // 0x0F = AUTH_RESPONSE