def test_proxy_login_with_kerberos_forbidden(self): """ Test that the proxy login fail when proxy role is not granted """ # Set up users for proxy login test self._setup_for_proxy(False) query = "select * from testkrbproxy.testproxy" # Try normal login with Charlie self.refresh_kerberos_tickets(self.bob_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider( service='dse', qops=["auth"], principal="*****@*****.**", authorization_id='*****@*****.**') self.assertRaises(NoHostAvailable, self.connect_and_query, auth_provider, query=query) self.refresh_kerberos_tickets(self.bob_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="*****@*****.**") self.assertRaises(Unauthorized, self.connect_and_query, auth_provider, query=query) self._remove_proxy_setup()
def test_connect_with_explicit_principal(self): """ This tests will attempt to authenticate using valid and invalid user principals @since 3.20 @jira_ticket PYTHON-574 @test_category dse auth @expected_result Client principals should be used by the underlying mechanism """ # Connect with valid principal self.refresh_kerberos_tickets(self.cassandra_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider( service='dse', qops=["auth"], principal="*****@*****.**") self.connect_and_query(auth_provider) connections = [ c for holders in self.cluster.get_connection_holders() for c in holders.get_connections() ] # Check to make sure our server_authenticator class is being set appropriate for connection in connections: self.assertTrue('DseAuthenticator' in connection.authenticator. server_authenticator_class) # Use invalid principal auth_provider = DSEGSSAPIAuthProvider( service='dse', qops=["auth"], principal="*****@*****.**") self.assertRaises(NoHostAvailable, self.connect_and_query, auth_provider)
def _setup_for_proxy(self, grant=True): os.environ['KRB5_CONFIG'] = self.krb_conf self.refresh_kerberos_tickets(self.cassandra_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider( service='dse', qops=["auth"], principal='*****@*****.**') cluster = Cluster(auth_provider=auth_provider) session = cluster.connect() stmts = [ "CREATE ROLE IF NOT EXISTS '{0}' WITH LOGIN = TRUE;".format( '*****@*****.**'), "CREATE ROLE IF NOT EXISTS '{0}' WITH LOGIN = TRUE;".format( '*****@*****.**'), "GRANT EXECUTE ON ALL AUTHENTICATION SCHEMES to '*****@*****.**'", "CREATE ROLE IF NOT EXISTS '{0}' WITH LOGIN = TRUE;".format( '*****@*****.**'), "GRANT EXECUTE ON ALL AUTHENTICATION SCHEMES to '*****@*****.**'", # Create a keyspace and allow only charlie to query it. "CREATE KEYSPACE testkrbproxy WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}", "CREATE TABLE testkrbproxy.testproxy (id int PRIMARY KEY, value text)", "GRANT ALL PERMISSIONS ON KEYSPACE testkrbproxy to '{0}'".format( '*****@*****.**'), ] if grant: stmts.append("GRANT PROXY.LOGIN ON ROLE '{0}' to '{1}'".format( '*****@*****.**', '*****@*****.**')) wait_role_manager_setup_then_execute(session, stmts) cluster.shutdown()
def test_should_not_athenticate_without_ticket(self): """ This tests will attempt to authenticate with a user that is valid but has no ticket @since 3.20 @jira_ticket PYTHON-457 @test_category dse auth @expected_result NoHostAvailable exception should be thrown """ auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) self.assertRaises(NoHostAvailable, self.connect_and_query, auth_provider)
def test_proxy_login_with_kerberos(self): """ Test that the proxy login works with kerberos. """ # Set up users for proxy login test self._setup_for_proxy() query = "select * from testkrbproxy.testproxy" # Try normal login with Charlie self.refresh_kerberos_tickets(self.charlie_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="*****@*****.**") self.connect_and_query(auth_provider, query=query) # Try proxy login with bob self.refresh_kerberos_tickets(self.bob_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider( service='dse', qops=["auth"], principal="*****@*****.**", authorization_id='*****@*****.**') self.connect_and_query(auth_provider, query=query) # Try logging with bob without mentioning charlie self.refresh_kerberos_tickets(self.bob_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"], principal="*****@*****.**") self.assertRaises(Unauthorized, self.connect_and_query, auth_provider, query=query) self._remove_proxy_setup()
def test_should_not_authenticate_with_bad_user_ticket(self): """ This tests will attempt to authenticate with a user that has a valid ticket, but is not a valid dse user. @since 3.20 @jira_ticket PYTHON-457 @test_category dse auth @expected_result NoHostAvailable exception should be thrown """ self.refresh_kerberos_tickets(self.dseuser_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) self.assertRaises(NoHostAvailable, self.connect_and_query, auth_provider)
def test_connect_with_kerberos_host_not_resolved(self): """ This tests will attempt to authenticate with IP, this will fail on osx. The success or failure of this test is dependent on a reverse dns lookup which can be impacted by your environment if it fails don't panic. @since 3.20 @jira_ticket PYTHON-566 @test_category dse auth @expected_result Client should error when ip is used """ self.refresh_kerberos_tickets(self.cassandra_keytab, "*****@*****.**", self.krb_conf) DSEGSSAPIAuthProvider(service='dse', qops=["auth"], resolve_host_name=False)
def test_host_resolution(self): # resolves by default provider = DSEGSSAPIAuthProvider(service='test', qops=QOP.all) authenticator = provider.new_authenticator('127.0.0.1') self.assertEqual(authenticator.sasl.host, 'localhost') # numeric fallback okay authenticator = provider.new_authenticator('192.0.2.1') self.assertEqual(authenticator.sasl.host, '192.0.2.1') # disable explicitly provider = DSEGSSAPIAuthProvider(service='test', qops=QOP.all, resolve_host_name=False) authenticator = provider.new_authenticator('127.0.0.1') self.assertEqual(authenticator.sasl.host, '127.0.0.1')
def get_auth_provider(config_file, env, username=None, password=None, options=None): def print_debug(message): if options and hasattr(options, "debug") and options.debug: sys.stderr.write(message) if username: print_debug("Using DSEPlainTextAuthProvider\n") return DSEPlainTextAuthProvider(username=username, password=password) """ Kerberos auth provider can be configured in the cqlshrc file [kerberos] section or with environment variables: Config option Environment Variable Description ------------- -------------------- ----------- service KRB_SERVICE Service to authenticate with qops QOPS Comma separated list of QOP values (default: auth) """ configs = configparser.SafeConfigParser() if sys.version_info < (3, 2) else configparser.ConfigParser() configs.read(config_file) def get_option(section, option, env_variable, default=None): value = env.get(env_variable) if value is None: try: value = configs.get(section, option) except configparser.Error: value = default return value krb_service = get_option('kerberos', 'service', 'KRB_SERVICE', 'dse') krb_qop_value = get_option('kerberos', 'qops', 'QOPS', 'auth') try: provider = DSEGSSAPIAuthProvider(service=krb_service, qops=krb_qop_value.split(',')) print_debug("Using DSEGSSAPIAuthProvider(service=%s, qops=%s)\n" % (krb_service, krb_qop_value)) print_debug(" This will only be used if the server requests kerberos authentication\n") return provider except ImportError as e: print_debug("Attempted to use DSEGSSAPIAuthProvider(service=%s, qops=%s)\n" % (krb_service, krb_qop_value)) print_debug(" Attempt failed because: %s\n" % str(e)) return None
def _remove_proxy_setup(self): os.environ['KRB5_CONFIG'] = self.krb_conf self.refresh_kerberos_tickets(self.cassandra_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider( service='dse', qops=["auth"], principal='*****@*****.**') cluster = Cluster(auth_provider=auth_provider) session = cluster.connect() session.execute("REVOKE PROXY.LOGIN ON ROLE '{0}' FROM '{1}'".format( '*****@*****.**', '*****@*****.**')) session.execute( "DROP ROLE IF EXISTS '{0}';".format('*****@*****.**')) session.execute( "DROP ROLE IF EXISTS '{0}';".format('*****@*****.**')) # Create a keyspace and allow only charlie to query it. session.execute("DROP KEYSPACE testkrbproxy") cluster.shutdown()
def test_connect_with_kerberos(self): """ This tests will attempt to authenticate with a user that is valid and has a ticket @since 3.20 @jira_ticket PYTHON-457 @test_category dse auth @expected_result Client should be able to connect and run a basic query """ self.refresh_kerberos_tickets(self.cassandra_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider() rs = self.connect_and_query(auth_provider) self.assertIsNotNone(rs) connections = [ c for holders in self.cluster.get_connection_holders() for c in holders.get_connections() ] # Check to make sure our server_authenticator class is being set appropriate for connection in connections: self.assertTrue('DseAuthenticator' in connection.authenticator. server_authenticator_class)
def test_connect_with_kerberos_and_graph(self): """ This tests will attempt to authenticate with a user and execute a graph query @since 3.20 @jira_ticket PYTHON-457 @test_category dse auth @expected_result Client should be able to connect and run a basic graph query with authentication """ self.refresh_kerberos_tickets(self.cassandra_keytab, "*****@*****.**", self.krb_conf) auth_provider = DSEGSSAPIAuthProvider(service='dse', qops=["auth"]) rs = self.connect_and_query(auth_provider) self.assertIsNotNone(rs) reset_graph(self.session, self._testMethodName.lower()) profiles = self.cluster.profile_manager.profiles profiles[ EXEC_PROFILE_GRAPH_DEFAULT].graph_options.graph_name = self._testMethodName.lower( ) self.session.execute_graph(ClassicGraphFixtures.classic()) rs = self.session.execute_graph('g.V()') self.assertIsNotNone(rs)