tableau / connector-plugin-sdk

SDK for Developing Tableau Connector Plugins
https://tableau.github.io/connector-plugin-sdk/
MIT License
108 stars 107 forks source link

Getting Unsupported authentication Mode dbimpersonate #711

Closed venkatmy closed 3 years ago

venkatmy commented 3 years ago

About You: Name: Venkat Company: Airbnb

We are trying to create a new connector using the Connector SDK that connects to Presto-Kerberos locally then uses database impersonation on the server.After publishing on the server, I keep getting this error

Error : Unsupported authentication mode db-impersonate Unable to connect to the Presto JDBC by Airbnb server localhost. Check that the server is running and that you have access privileges to the requested database.

I do not see any DelegationUID property in the JDBC Presto documentation that has this is variable. I only a variable named user.

nas account.

devanshsoni9 commented 3 years ago

Hi Venkat As mentioned in the connector SDK documentation, at this point we support "Impersonate using embedded password" only for the database impersonation auth. This explains why you would get the error.

The DelegationUID property is specific to the Impala JDBC driver. The PrestoDB JDBC driver documentation does not mention anything about supporting Delegation. But I know Presto has other vendors which provide JDBC drivers and I am not sure about their support for DelegationUID.

venkatmy commented 3 years ago

Thanks Devan, Based on your feedback, looks like impersonation is not going to work with the current JDBC Presto Driver that we have. Here is what I am trying to do instead

if (attr[connectionHelper.attributeAuthentication] == "auth-integrated") {
        var tableauServerUser = attr[connectionHelper.attributeTableauServerUser];
        // tableauServerUser is not empty means this is a Tableau Server Environment        
            if (!isEmpty(tableauServerUser)) {
                props["user"] = tableauServerUser;   

            } else {
        // properties for Kerberos SSO on Tableau Desktop   
            props["user"] = attr[connectionHelper.attributeUsername];
            props["SSL"] = "true";
            props["SSLKeyStorePath"] = "/Users/venkata_mylavarapu/presto-client.jks";
            props["SSLKeyStorePassword"] = "********";
            props["KerberosRemoteServiceName"] = "presto";
            props["KerberosUseCanonicalHostname"] = "false";
            props["KerberosPrincipal"] = "venkata_mylavarapu@TEST.MUSTA.CH";
            props["KerberosConfigPath"] = "/Library/Preferences/edu.mit.Kerberos";
            props["KerberosUseCredentialCache"] = "true"; 

            }    
        }   

As you see, when we run locally, the else condition is executed --> I am passing all the kerberos properties along with the username.

venkatmy commented 3 years ago

Can I get some feedback and guidance on this. We are stuck and are unable to proceed further. It appears the basic javascript logging calls like console.log("") function does not work either to get information.

devanshsoni9 commented 3 years ago

Hi Venkat,

I really do not understand the case for passing viewer username when Kerberos is not enabled on the server. Are you implying that this could work in place of the DelegationUID ? If so, you can try Impersonate via embedded credentials if the users are setup with the correct delegation privileges on the database.

Otherwise, I can consider adding support for database impersonation with Impersonate via Runas (Kerberos configured on Server) as a feature request. I am sorry about not adding all forms of database impersonation . It was done on an ad-hoc customer request.

For logging in javascript files in the SDK you could use logging.Log("") as mentioned in the docs.

venkatmy commented 3 years ago

Hi Devan All we are trying to do is edit the connection string when the connector detects that it is a server environment, it will send an updated hostname, port and username that becomes the tableau server user name. Since the generic JDBC Presto driver allows only one parameter named "user" we are trying to replace this with the Thanks I tested the logging.Log() property and it works only on Desktop. When I tried on the tableau server, this is not being captured at all. Turned the debug level for server and navigated thru data-server logs but did not find helpful information.

devanshsoni9 commented 3 years ago

HI Venkat, What is the authentication mode when you publish the workbook to the Tableau Server ? Screen Shot 2021-02-10 at 12 56 08 AM

venkatmy commented 3 years ago

Screen Shot 2021-02-09 at 9 55 41 PM

I do not get this option anymore after I removed this variable from the manifest.xml Here is my content of the manifest.xml `

`

venkatmy commented 3 years ago

I think we will be best served by having working sessions on these, our understanding of Connector SDK is limited and need to really understand the workings of these components.

devanshsoni9 commented 3 years ago

Hey Venkat,

Can you confirm that when are connecting to the database on Tableau Desktop, you use the Integrated Authentication mode ? If you use integrated auth, then you should get the Server Run As Account authentication option while publishing. I suggest following the steps mentioned below to make sure RunAs authentication is configured on Tableau Server.

For Kerberos RunAs authentication, users need to provide RunAs user principal name and a keytab file path. Tableau Server uses the keytab to login to Kerberos KDC and the TGT thus obtained is used by JDBC driver for making a database connection. For configuring a Tableau Server on Linux, see this Tableau article. For configuring a Tableau Server on Windows, see this Tableau article.

Hopefully it helps resolve your issue.

venkatmy commented 3 years ago

Hi Devan, Yes I am using the Auth Integrated mode. In the connection fields file there is a drop down option for the auth mode. It still however does not give me a server run as option.

<?xml` version="1.0" encoding="utf-8"?>

<connection-fields>

  <field name="server" label="Server" category="endpoint" value-type="string"/>

  <field name="port" label="Port" category="endpoint" value-type="string" default-value="50002"/>

  <field name="authentication" label="Authentication" category="authentication" value-type="selection" >
    <selection-group>
      <option value="auth-integrated" label="Kerberos"/>
      <option value="auth-user-pass" label="Username and Password"/>
    </selection-group>
  </field>

  <field name="username" label="Username" category="authentication" value-type="string">
    <conditions>
      <condition field="authentication" value="auth-integrated"/>
    </conditions>
  </field>

  <field name="password" label="Password" category="authentication" value-type="string" secure="true">
    <conditions>
      <condition field="authentication" value="auth-user-pass"/>
    </conditions>
  </field>

  <field name="sslmode" label="Require SSL" value-type="boolean" category="general" default-value="" >
    <boolean-options>
      <false-value value="" />
      <true-value value="require" />
    </boolean-options>
  </field>
</connection-fields>
venkatmy commented 3 years ago

Here is the connection properties file where I am checking for the auth-integrated option and passing the credentials accordingly. As you see, if the connector runs in the server environment I am trying to replace the user parameter with the tableauserveruser attribute value.

if (attr[connectionHelper.attributeAuthentication] == "auth-integrated") {
        var tableauServerUser = attr[connectionHelper.attributeTableauServerUser];
        // tableauServerUser is not empty means this is a Tableau Server Environment        
            if (!isEmpty(tableauServerUser)) {
                props["user"] = tableauServerUser;   

            } else {
        // properties for Kerberos SSO on Tableau Desktop   
            props["user"] = attr[connectionHelper.attributeUsername];
            props["SSL"] = "true";
            props["SSLKeyStorePath"] = "/Users/venkata_mylavarapu/presto-client.jks";
            props["SSLKeyStorePassword"] = "********";
            props["KerberosRemoteServiceName"] = "presto";
            props["KerberosUseCanonicalHostname"] = "false";
            props["KerberosPrincipal"] = "venkata_mylavarapu@TEST.MUSTA.CH";
            props["KerberosConfigPath"] = "/Library/Preferences/edu.mit.Kerberos";
            props["KerberosUseCredentialCache"] = "true"; 

            }    
        }   
devanshsoni9 commented 3 years ago

yeah , those two files look good to me. You might need to configure Tableau Server for Kerberos RunAs auth

For Kerberos RunAs authentication, users need to provide RunAs user principal name and a keytab file path. Tableau Server uses the keytab to login to Kerberos KDC and the TGT thus obtained is used by JDBC driver for making a database connection. For configuring a Tableau Server on Linux, see this Tableau article. For configuring a Tableau Server on Windows, see this Tableau article.

venkatmy commented 3 years ago

Thank Devan, I will review the doc and also share this with the rest of my team. The document however states that the supported kerberos delegation with the instructions provided is only Oracle.. Does this apply to Presto and potentially other data sources that use JDBC driver ? I am a little confused as the top line states you can enable this for JDBC but then the supported section lists only Oracle. Please advise.

devanshsoni9 commented 3 years ago

The link for Linux is pointing to Delegation docs but I really meant RunAs docs. This is the corrected link for Linux server https://help.tableau.com/current/server-linux/en-us/kerberos_runas_linux.htm

devanshsoni9 commented 3 years ago

The JDBC RunAs and Delegation docs were written by testing Oracle connector in Tableau which now defaults to JDBC connection (previously OCI). But we do know the same steps would work for other JDBC-based connections like is documented for PostgreSQL in the SDK docs.

Also the comment about Kerberos delegation in the RunAs article about probably does not belong there. I will internally open a request to fine tune that documentation

venkatmy commented 3 years ago

Hi Devan, I have reviewed the documentation and here is what I understood

  1. Need to create a new RunAs Service Account.
  2. Our Tableau Server is on Windows Environment by the way, this service account should have read access to the DB and also have Explorer (Can Publish) role on the tableau server.
  3. Enable delegation property on the service account.
  4. Set up the Kerberos Delegation thru TSM commands
  5. This will enable RunAs Service Account and also will be able to delegate the viewer users when they view the dashboards with live queries. (This is applicable to only Live connections and not data extracts) Please confirm if my understanding is correct and we are testing this the right way.
  6. We have a service account that runs the tableau server on the Windows Server. I am assuming the documentation is refering to a new service account specifically created for kerberos delegation. please clarify this is the case.
venkatmy commented 3 years ago

Hi Devan, I have a few additional questions on the documentation - https://community.tableau.com/s/question/0D54T00000F33OI/enable-delegation-for-hiveimpala that was shared during the meeiting. I am not very clear on this text After configuring Tableau Server for Kerberos, enabling constrained delegation for Kerberos to Hive/Impala requires you to specify the Tableau Server Run As User for delegation. You must also add the Hive/Impala services account for delegation in Active Directory. Can you please elaborate more on this. The RunAs account is already an Active Directory account. Does this mean the same account needs to be created in Presto DB ? Please clarify. Thank you!.

devanshsoni9 commented 3 years ago

This is different from a Tableau Server's RunAs account. This account is used for creating a keytab file with a Kerberos principal, which is used for configuring Kerberos delegation. For configuring delegation on your database, please consult the vendors documentation.

devanshsoni9 commented 3 years ago

I can see in presto docs, they mention steps for MIT Kerberos https://prestodb.io/docs/current/security/server.html#kerberos-principals-and-keytab-files

jkoskela commented 3 years ago

"Need to create a new RunAs Service Account."

"Our Tableau Server is on Windows Environment by the way, this service account should have read access to the DB and also have Explorer (Can Publish) role on the tableau server."

"We have a service account that runs the tableau server on the Windows Server. I am assuming the documentation is refering to a new service account specifically created for kerberos delegation. please clarify this is the case."

One caveat to all of this is that we have not validated that Kerberos constrained delegation works for the PrestoDB Presto driver. @devanshsoni9 reported an issue with it when we tested 2 years ago, which was not resolved. I would suggest just writing a test program in Java first to test the driver. There are other drivers such as Simba's or CData's which you could also try.

jkoskela commented 3 years ago

@venkatmy I reported the problem with logging to the plugin team and they said that you need to enable debug logging for Tableau, or the plugin logging won't show up at all. From the docs:

You can write to the Tableau log file (tabprotosrv.txt). Writing to the log file requires Debug level logging (-DLogLevel=Debug). Use care when logging so that you don’t expose sensitive information like passwords and other authentication information.

Did you enable debug logging for Tableau Server?

venkatmy commented 3 years ago

Yes I enabled the debug logging for tableau server. I will run this thru again and see if this works.

venkatmy commented 3 years ago

1) After reviewing the Kerberos Delegation setup instructions we figured that PrestoDB needs to be configured with Active Directory to complete the set up along with Tableau Server. Our PrestoDB currently does not not talk to AD. Connecting Presto DB to AD is not a trivial thing to do, hence we are looking for additional options - Is it possible to tweak the generic JDBC Presto Driver or your JDBC layer to pass viewer credentials. Is there any other way other than delegation to extract the viewer username and pass it to the JDBC properties file. 2) How does the DB Impersonation work with JDBC drivers that are not inherently designed to support Impersonation. Does Tableau Server validate if the Datasource actually supports impersonation. Our understanding is that this is transparent to Tableau as we are just passing the parameters via a JDBC properties file. In one of your examples hive needed two parameters UID and DelegationUID in the JDBC properties.

devanshsoni9 commented 3 years ago

resolving this as partner was provided the issue resolution offline.