| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| from tests.beeswax.impala_beeswax import ImpalaBeeswaxException |
| from tests.common.impala_test_suite import ImpalaTestSuite |
| |
| |
| class TestBeeswax(ImpalaTestSuite): |
| |
| def test_user_validation(self): |
| """Test various scenarios with cross-connection operations with the same |
| and different users.""" |
| USER1 = "user1" |
| USER2 = "user2" |
| client1 = self.client |
| different_user_client = None |
| unset_user_client = None |
| try: |
| same_user_client = self.create_impala_client(protocol='beeswax') |
| different_user_client = self.create_impala_client(protocol='beeswax') |
| unset_user_client = self.create_impala_client(protocol='beeswax') |
| |
| # Unauthenticated Beewax only sets user once the query is run. |
| result = client1.execute("select effective_user()", user=USER1) |
| assert result.data[0] == USER1 |
| result = same_user_client.execute("select effective_user()", user=USER1) |
| assert result.data[0] == USER1 |
| # The user shouldn't change once set. |
| result = client1.execute("select effective_user()", user=USER2) |
| assert result.data[0] == USER1 |
| result = different_user_client.execute("select effective_user()", user=USER2) |
| assert result.data[0] == USER2 |
| |
| QUERY = "select * from functional.alltypes" |
| handle = client1.execute_async(QUERY) |
| client1.get_state(handle) |
| # Connections with a effective user should not be able to access other users' |
| # sessions. |
| self._assert_invalid_handle(lambda: different_user_client.fetch(QUERY, handle)) |
| self._assert_invalid_handle(lambda: different_user_client.get_state(handle)) |
| self._assert_invalid_handle(lambda: different_user_client.get_log(handle)) |
| self._assert_profile_access_denied( |
| lambda: different_user_client.get_runtime_profile(handle)) |
| self._assert_profile_access_denied( |
| lambda: different_user_client.get_exec_summary(handle)) |
| self._assert_invalid_handle(lambda: different_user_client.close_dml(handle)) |
| |
| # Connections with the same user can always access the requests. A connection |
| # without an effective user (only possible with unauthenticated connections) |
| # is allowed to access any query. Some Impala tests depend on this. |
| for valid_client in [client1, same_user_client, unset_user_client]: |
| valid_client.get_state(handle) |
| valid_client.fetch(QUERY, handle) |
| valid_client.get_log(handle) |
| valid_client.get_runtime_profile(handle) |
| valid_client.get_exec_summary(handle) |
| |
| # Validation of user should be skipped for closing and cancelling queries, to |
| # avoid breaking administrative tools that clean up queries via Beeswax RPCs. |
| different_user_client.cancel(handle) |
| different_user_client.close_query(handle) |
| finally: |
| if different_user_client is not None: |
| different_user_client.close() |
| if unset_user_client is not None: |
| unset_user_client.close() |
| |
| def _assert_invalid_handle(self, fn): |
| """Assert that invoking fn() raises an ImpalaBeeswaxException with an invalid query |
| handle error.""" |
| try: |
| fn() |
| assert False, "Expected invalid handle" |
| except ImpalaBeeswaxException, e: |
| assert "Query id" in str(e) and "not found" in str(e), str(e) |
| |
| def _assert_profile_access_denied(self, fn): |
| """Assert that invoking fn() raises an ImpalaBeeswaxException with the error |
| message indicating that profile access is denied.""" |
| try: |
| fn() |
| assert False, "Expected invalid handle" |
| except ImpalaBeeswaxException, e: |
| assert "is not authorized to access the runtime profile" in str(e), str(e) |