| <!DOCTYPE HTML> |
| <html lang="en-US"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>Security</title> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <meta name="generator" content="Jekyll v4.2.2"> |
| <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic,900"> |
| <link rel="stylesheet" href="/avatica/css/screen.css"> |
| <link rel="icon" type="image/x-icon" href="/avatica/favicon.ico"> |
| </head> |
| |
| |
| <body class="wrap"> |
| <header role="banner"> |
| <nav class="mobile-nav show-on-mobiles"> |
| <ul> |
| <li class=""> |
| <a href="/avatica/">Home</a> |
| </li> |
| <li class=""> |
| <a href="/avatica/downloads/">Download</a> |
| </li> |
| <li class=""> |
| <a href="/avatica/community/">Community</a> |
| </li> |
| <li class=""> |
| <a href="/avatica/develop/">Develop</a> |
| </li> |
| <li class=""> |
| <a href="/avatica/news/">News</a> |
| </li> |
| <li class="current"> |
| <a href="/avatica/docs/">Docs</a> |
| </li> |
| </ul> |
| |
| </nav> |
| <div class="grid"> |
| <div class="unit one-third center-on-mobiles"> |
| <h1> |
| <a href="/avatica/"> |
| <span class="sr-only">Apache Calcite Avatica</span> |
| <img src="/avatica/img/logo.png" width="226" height="140" alt="Calcite Logo"> |
| </a> |
| </h1> |
| </div> |
| <nav class="main-nav unit two-thirds hide-on-mobiles"> |
| <ul> |
| <li class=""> |
| <a href="/avatica/">Home</a> |
| </li> |
| <li class=""> |
| <a href="/avatica/downloads/">Download</a> |
| </li> |
| <li class=""> |
| <a href="/avatica/community/">Community</a> |
| </li> |
| <li class=""> |
| <a href="/avatica/develop/">Develop</a> |
| </li> |
| <li class=""> |
| <a href="/avatica/news/">News</a> |
| </li> |
| <li class="current"> |
| <a href="/avatica/docs/">Docs</a> |
| </li> |
| </ul> |
| |
| </nav> |
| </div> |
| </header> |
| |
| |
| <section class="docs"> |
| <div class="grid"> |
| |
| <div class="docs-nav-mobile unit whole show-on-mobiles"> |
| <select onchange="if (this.value) window.location.href=this.value"> |
| <option value="">Navigate the docs…</option> |
| |
| <optgroup label="Overview"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| </optgroup> |
| |
| <optgroup label="Avatica Reference"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| </optgroup> |
| |
| <optgroup label="Avatica Go Client Reference"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| </optgroup> |
| |
| <optgroup label="Avatica Meta"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| </optgroup> |
| |
| <optgroup label="Avatica Go Client Meta"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| </optgroup> |
| |
| </select> |
| </div> |
| |
| |
| <div class="unit four-fifths"> |
| <article> |
| <h1>Security</h1> |
| <!-- |
| |
| --> |
| |
| <p>Security is an important topic between clients and the Avatica server. Most JDBC |
| drivers and databases implement some level of authentication and authorization |
| for limit what actions clients are allowed to perform.</p> |
| |
| <p>Similarly, Avatica must limit what users are allowed to connect and interact |
| with the server. Avatica must primarily deal with authentication while authorization |
| is deferred to the underlying database. By default, Avatica provides no authentication. |
| Avatica does have the ability to perform client authentication using Kerberos, |
| HTTP Basic, and HTTP Digest.</p> |
| |
| <p>The authentication and authorization provided by Avatica are designed for use |
| <em>instead</em> of the authentication and authorization provided by the underlying database. |
| The typical <code class="language-plaintext highlighter-rouge">user</code> and <code class="language-plaintext highlighter-rouge">password</code> JDBC properties are <strong>always</strong> passed through to |
| the Avatica server which will cause the server to enforce those credentials. As such, |
| Avatica’s authentication types mentioned here only have relevance when the underlying database’s authentication |
| and authorization features are not used. (The Kerberos/SPNEGO integration is one difference as the impersonation feature |
| is specifically designed to allow the Kerberos identity to be passed to the database - |
| new advanced implementations could also follow this same approach if desired).</p> |
| |
| <h2 id="table-of-contents">Table of Contents</h2> |
| <ul> |
| <li><a href="#http-basic-authentication">HTTP Basic</a></li><li><a href="#http-digest-authentication">HTTP Digest</a></li><li><a href="#kerberos-with-spnego-authentication">Kerberos with SPNEGO</a></li><li><a href="#custom-authentication">Custom Authentication</a></li><li><a href="#client-implementation">Client implementation</a></li><li><a href="#tls">TLS</a></li> |
| </ul> |
| |
| <h2 id="http-basic-authentication">HTTP Basic Authentication</h2> |
| |
| <p>Avatica supports authentication over <a href="https://en.wikipedia.org/wiki/Basic_access_authentication">HTTP Basic</a>. |
| This is simple username-password based authentication which is ultimately insecure when |
| operating over an untrusted network. Basic authentication is only secure when the transport |
| is encrypted (e.g. TLS) as the credentials are passed in the clear. This authentication is |
| supplementary to the provided JDBC authentication. If credentials are passed to the database |
| already, this authentication is unnecessary.</p> |
| |
| <h3 id="enabling-basic-authentication">Enabling Basic Authentication</h3> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">String</span> <span class="n">propertiesFile</span> <span class="o">=</span> <span class="s">"/path/to/jetty-users.properties"</span><span class="o">;</span> |
| <span class="c1">// All roles allowed</span> |
| <span class="nc">String</span><span class="o">[]</span> <span class="n">allowedRoles</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[]</span> <span class="o">{</span><span class="s">"*"</span><span class="o">};</span> |
| <span class="c1">// Only specific roles are allowed</span> |
| <span class="n">allowedRoles</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[]</span> <span class="o">{</span> <span class="s">"users"</span><span class="o">,</span> <span class="s">"admins"</span> <span class="o">};</span> |
| <span class="nc">HttpServer</span> <span class="n">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HttpServer</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> |
| <span class="o">.</span><span class="na">withPort</span><span class="o">(</span><span class="mi">8765</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withHandler</span><span class="o">(</span><span class="k">new</span> <span class="nc">LocalService</span><span class="o">(),</span> <span class="nc">Driver</span><span class="o">.</span><span class="na">Serialization</span><span class="o">.</span><span class="na">PROTOBUF</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withBasicAuthentication</span><span class="o">(</span><span class="n">propertiesFile</span><span class="o">,</span> <span class="n">allowedRoles</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">build</span><span class="o">();</span></code></pre></figure> |
| |
| <p>The properties file must be in a form consumable by Jetty. Each line in this |
| file is of the form: <code class="language-plaintext highlighter-rouge">username: password[,rolename ...]</code></p> |
| |
| <p>For example:</p> |
| |
| <figure class="highlight"><pre><code class="language-properties" data-lang="properties"><span class="py">bob</span><span class="p">:</span> <span class="s">b0b5pA55w0rd,users</span> |
| <span class="py">steve</span><span class="p">:</span> <span class="s">5teve5pA55w0rd,users</span> |
| <span class="py">alice</span><span class="p">:</span> <span class="s">Al1cepA55w0rd,admins</span></code></pre></figure> |
| |
| <p>Passwords can also be obfuscated as MD5 hashes or oneway cryptography (“CRYPT”). |
| For more information, see the <a href="http://www.eclipse.org/jetty/documentation/current/configuring-security-secure-passwords.html">official Jetty documentation</a>.</p> |
| |
| <h2 id="http-digest-authentication">HTTP Digest Authentication</h2> |
| |
| <p>Avatica also supports <a href="https://en.wikipedia.org/wiki/Digest_access_authentication">HTTP Digest</a>. |
| This is desirable for Avatica as it does not require the use of TLS to secure communication |
| between the Avatica client and server. It is configured very similarly to HTTP Basic |
| authentication. This authentication is supplementary to the provided JDBC authentication. |
| If credentials are passed to the database already, this authentication is unnecessary.</p> |
| |
| <h3 id="enabling-digest-authentication">Enabling Digest Authentication</h3> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">String</span> <span class="n">propertiesFile</span> <span class="o">=</span> <span class="s">"/path/to/jetty-users.properties"</span><span class="o">;</span> |
| <span class="c1">// All roles allowed</span> |
| <span class="nc">String</span><span class="o">[]</span> <span class="n">allowedRoles</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[]</span> <span class="o">{</span><span class="s">"*"</span><span class="o">};</span> |
| <span class="c1">// Only specific roles are allowed</span> |
| <span class="n">allowedRoles</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[]</span> <span class="o">{</span> <span class="s">"users"</span><span class="o">,</span> <span class="s">"admins"</span> <span class="o">};</span> |
| <span class="nc">HttpServer</span> <span class="n">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HttpServer</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> |
| <span class="o">.</span><span class="na">withPort</span><span class="o">(</span><span class="mi">8765</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withHandler</span><span class="o">(</span><span class="k">new</span> <span class="nc">LocalService</span><span class="o">(),</span> <span class="nc">Driver</span><span class="o">.</span><span class="na">Serialization</span><span class="o">.</span><span class="na">PROTOBUF</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withDigestAuthentication</span><span class="o">(</span><span class="n">propertiesFile</span><span class="o">,</span> <span class="n">allowedRoles</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">build</span><span class="o">();</span></code></pre></figure> |
| |
| <p>The properties file must be in a form consumable by Jetty. Each line in this |
| file is of the form: <code class="language-plaintext highlighter-rouge">username: password[,rolename ...]</code></p> |
| |
| <p>For example:</p> |
| |
| <figure class="highlight"><pre><code class="language-properties" data-lang="properties"><span class="py">bob</span><span class="p">:</span> <span class="s">b0b5pA55w0rd,users</span> |
| <span class="py">steve</span><span class="p">:</span> <span class="s">5teve5pA55w0rd,users</span> |
| <span class="py">alice</span><span class="p">:</span> <span class="s">Al1cepA55w0rd,admins</span></code></pre></figure> |
| |
| <p>Passwords can also be obfuscated as MD5 hashes or oneway cryptography (“CRYPT”). |
| For more information, see the <a href="http://www.eclipse.org/jetty/documentation/current/configuring-security-secure-passwords.html">official Jetty documentation</a>.</p> |
| |
| <h2 id="kerberos-with-spnego-authentication">Kerberos with SPNEGO Authentication</h2> |
| |
| <p>Because Avatica operates over an HTTP interface, the simple and protected GSSAPI |
| negotiation mechanism (<a href="https://en.wikipedia.org/wiki/SPNEGO">SPNEGO</a>) is a logical |
| choice. This mechanism makes use of the “HTTP Negotiate” authentication extension to |
| communicate with the Kerberos Key Distribution Center (KDC) to authenticate a client.</p> |
| |
| <h3 id="enabling-spnegokerberos-authentication-in-servers">Enabling SPNEGO/Kerberos Authentication in servers</h3> |
| |
| <p>The Avatica server can operate either by performing the login using |
| a JAAS configuration file or login programmatically. By default, authenticated clients |
| will have queries executed as the Avatica server’s kerberos user. <a href="#impersonation">Impersonation</a> |
| is the feature which enables actions to be run in the server as the actual end-user.</p> |
| |
| <p>As a note, it is required that the Kerberos principal in use by the Avatica server |
| <strong>must</strong> have an primary of <code class="language-plaintext highlighter-rouge">HTTP</code> (where Kerberos principals are of the form |
| <code class="language-plaintext highlighter-rouge">primary[/instance]@REALM</code>). This is specified by <a href="https://tools.ietf.org/html/rfc4559">RFC-4559</a>.</p> |
| |
| <h4 id="programmatic-login">Programmatic Login</h4> |
| |
| <p>This approach requires no external file configurations and only requires a |
| keytab file for the principal.</p> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">HttpServer</span> <span class="n">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HttpServer</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> |
| <span class="o">.</span><span class="na">withPort</span><span class="o">(</span><span class="mi">8765</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withHandler</span><span class="o">(</span><span class="k">new</span> <span class="nc">LocalService</span><span class="o">(),</span> <span class="nc">Driver</span><span class="o">.</span><span class="na">Serialization</span><span class="o">.</span><span class="na">PROTOBUF</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withSpnego</span><span class="o">(</span><span class="s">"HTTP/host.domain.com@DOMAIN.COM"</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withAutomaticLogin</span><span class="o">(</span> |
| <span class="k">new</span> <span class="nf">File</span><span class="o">(</span><span class="s">"/etc/security/keytabs/avatica.spnego.keytab"</span><span class="o">))</span> |
| <span class="o">.</span><span class="na">build</span><span class="o">();</span></code></pre></figure> |
| |
| <h4 id="jaas-configuration-file-login">JAAS Configuration File Login</h4> |
| |
| <p><strong>Since Avatica 1.20.0, Jetty has removed this functionality which means that Avatica |
| also does not support Avatica server login via JAAS configuration file. The Avatica |
| programmatic login is the only manner to do this.</strong></p> |
| |
| <p>A JAAS configuration file can be set via the system property <code class="language-plaintext highlighter-rouge">java.security.auth.login.config</code>. |
| The user must set this property when launching their Java application invoking the Avatica server. |
| The presence of this file will automatically perform login as necessary in the first use |
| of the Avatica server. The invocation is nearly the same as the programmatic login.</p> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">HttpServer</span> <span class="n">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HttpServer</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> |
| <span class="o">.</span><span class="na">withPort</span><span class="o">(</span><span class="mi">8765</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withHandler</span><span class="o">(</span><span class="k">new</span> <span class="nc">LocalService</span><span class="o">(),</span> <span class="nc">Driver</span><span class="o">.</span><span class="na">Serialization</span><span class="o">.</span><span class="na">PROTOBUF</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withSpnego</span><span class="o">(</span><span class="s">"HTTP/host.domain.com@DOMAIN.COM"</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">build</span><span class="o">();</span></code></pre></figure> |
| |
| <p>The contents of the JAAS configuration file are very specific:</p> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">com</span><span class="o">.</span><span class="na">sun</span><span class="o">.</span><span class="na">security</span><span class="o">.</span><span class="na">jgss</span><span class="o">.</span><span class="na">accept</span> <span class="o">{</span> |
| <span class="n">com</span><span class="o">.</span><span class="na">sun</span><span class="o">.</span><span class="na">security</span><span class="o">.</span><span class="na">auth</span><span class="o">.</span><span class="na">module</span><span class="o">.</span><span class="na">Krb5LoginModule</span> <span class="n">required</span> |
| <span class="n">storeKey</span><span class="o">=</span><span class="kc">true</span> |
| <span class="n">useKeyTab</span><span class="o">=</span><span class="kc">true</span> |
| <span class="n">keyTab</span><span class="o">=/</span><span class="n">etc</span><span class="o">/</span><span class="n">security</span><span class="o">/</span><span class="n">keytabs</span><span class="o">/</span><span class="n">avatica</span><span class="o">.</span><span class="na">spnego</span><span class="o">.</span><span class="na">keyTab</span> |
| <span class="n">principal</span><span class="o">=</span><span class="no">HTTP</span><span class="o">/</span><span class="n">host</span><span class="o">.</span><span class="na">domain</span><span class="o">.</span><span class="na">com</span><span class="nd">@DOMAIN</span><span class="o">.</span><span class="na">COM</span><span class="o">;</span> |
| <span class="o">};</span></code></pre></figure> |
| |
| <p>Ensure the <code class="language-plaintext highlighter-rouge">keyTab</code> and <code class="language-plaintext highlighter-rouge">principal</code> attributes are set correctly for your system.</p> |
| |
| <h4 id="additional-allowed-realms">Additional Allowed Realms</h4> |
| |
| <p>Versions of Avatica prior to 1.20.0 provided API to specify a list of <code class="language-plaintext highlighter-rouge">additionalAllowedRealms</code>. |
| While this API could have been leveraged by other integrators of Avatica, the only provided |
| usage of this API was to specify additional Kerberos realms (realms other than the kerberos |
| realm which the server’s principal was a part of) which should be allowed to authenticate |
| against the Avatica server.</p> |
| |
| <p>With the Jetty update in Avatica 1.20.0, this functionality was removed without replacement. |
| Any user with valid Kerberos credentials which can be validated based on the krb5.conf file |
| on the host where the Avatica server runs should be capable of authenticating against Avatica. |
| Consult your JVM to determine where the default krb5.conf file is loaded from and the Java |
| system property to use if you need to override this file.</p> |
| |
| <h3 id="impersonation">Impersonation</h3> |
| |
| <p>Impersonation is a feature of the Avatica server which allows the Avatica clients |
| to execute the server-side calls (e.g. the underlying JDBC calls). Because the details |
| on what it means to execute such an operation are dependent on the actual system, a |
| callback is exposed for downstream integrators to implement.</p> |
| |
| <p>For example, the following is an example for creating an Apache Hadoop <code class="language-plaintext highlighter-rouge">UserGroupInformation</code> |
| “proxy user”. This example takes a <code class="language-plaintext highlighter-rouge">UserGroupInformation</code> object representing the Avatica server’s |
| identity, creates a “proxy user” with the client’s username, and performs the action as that |
| client but using the server’s identity.</p> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">PhoenixDoAsCallback</span> <span class="kd">implements</span> <span class="nc">DoAsRemoteUserCallback</span> <span class="o">{</span> |
| <span class="kd">private</span> <span class="kd">final</span> <span class="nc">UserGroupInformation</span> <span class="n">serverUgi</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="nf">PhoenixDoAsCallback</span><span class="o">(</span><span class="nc">UserGroupInformation</span> <span class="n">serverUgi</span><span class="o">)</span> <span class="o">{</span> |
| <span class="k">this</span><span class="o">.</span><span class="na">serverUgi</span> <span class="o">=</span> <span class="nc">Objects</span><span class="o">.</span><span class="na">requireNonNull</span><span class="o">(</span><span class="n">serverUgi</span><span class="o">);</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Override</span> |
| <span class="kd">public</span> <span class="o"><</span><span class="no">T</span><span class="o">></span> <span class="no">T</span> <span class="nf">doAsRemoteUser</span><span class="o">(</span><span class="nc">String</span> <span class="n">remoteUserName</span><span class="o">,</span> <span class="nc">String</span> <span class="n">remoteAddress</span><span class="o">,</span> <span class="kd">final</span> <span class="nc">Callable</span><span class="o"><</span><span class="no">T</span><span class="o">></span> <span class="n">action</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span> |
| <span class="c1">// Proxy this user on top of the server's user (the real user)</span> |
| <span class="nc">UserGroupInformation</span> <span class="n">proxyUser</span> <span class="o">=</span> <span class="nc">UserGroupInformation</span><span class="o">.</span><span class="na">createProxyUser</span><span class="o">(</span><span class="n">remoteUserName</span><span class="o">,</span> <span class="n">serverUgi</span><span class="o">);</span> |
| |
| <span class="c1">// Check if this user is allowed to be impersonated.</span> |
| <span class="c1">// Will throw AuthorizationException if the impersonation as this user is not allowed</span> |
| <span class="nc">ProxyUsers</span><span class="o">.</span><span class="na">authorize</span><span class="o">(</span><span class="n">proxyUser</span><span class="o">,</span> <span class="n">remoteAddress</span><span class="o">);</span> |
| |
| <span class="c1">// Execute the actual call as this proxy user</span> |
| <span class="k">return</span> <span class="n">proxyUser</span><span class="o">.</span><span class="na">doAs</span><span class="o">(</span><span class="k">new</span> <span class="nc">PrivilegedExceptionAction</span><span class="o"><</span><span class="no">T</span><span class="o">>()</span> <span class="o">{</span> |
| <span class="nd">@Override</span> |
| <span class="kd">public</span> <span class="no">T</span> <span class="nf">run</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">action</span><span class="o">.</span><span class="na">call</span><span class="o">();</span> |
| <span class="o">}</span> |
| <span class="o">});</span> |
| <span class="o">}</span> |
| <span class="o">}</span></code></pre></figure> |
| |
| <h4 id="remote-user-extraction">Remote user extraction</h4> |
| |
| <p>In some cases, it may be desirable to execute some queries on behalf of another user. For example, |
| <a href="https://knox.apache.org">Apache Knox</a> has a gateway service which can act as a proxy for all requests |
| to the backend Avatica server. In this case, we don’t want to run the queries as the Knox user, instead |
| the real user communicating with Knox.</p> |
| |
| <p>There are presently two options to extract the “real” user from HTTP requests:</p> |
| |
| <ul> |
| <li>The authenticated user from the HTTP request, <code class="language-plaintext highlighter-rouge">org.apache.calcite.avatica.server.HttpRequestRemoteUserExtractor</code> (default)</li> |
| <li>The value of a parameter in the HTTP query string, <code class="language-plaintext highlighter-rouge">org.apache.calcite.avatica.server.HttpQueryStringParameterRemoteUserExtractor</code> (e.g “doAs”)</li> |
| </ul> |
| |
| <p>Implementations of Avatica can configure this using the <code class="language-plaintext highlighter-rouge">AvaticaServerConfiguration</code> and providing |
| an implementation of <code class="language-plaintext highlighter-rouge">RemoteUserExtractor</code>. There are two implementations provided as listed above.</p> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">config</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">AvaticaServerConfiguration</span><span class="o">()</span> <span class="o">{</span> |
| <span class="cm">/* ... */</span> |
| <span class="nd">@Override</span> <span class="kd">public</span> <span class="nc">RemoteUserExtractor</span> <span class="nf">getRemoteUserExtractor</span><span class="o">()</span> <span class="o">{</span> |
| <span class="c1">// We extract the "real" user via the "doAs" query string parameter</span> |
| <span class="k">return</span> <span class="k">new</span> <span class="nf">HttpQueryStringParameterRemoteUserExtractor</span><span class="o">(</span><span class="s">"doAs"</span><span class="o">);</span> |
| <span class="o">}</span> |
| <span class="cm">/* ... */</span> |
| <span class="o">};</span></code></pre></figure> |
| |
| <h2 id="custom-authentication">Custom Authentication</h2> |
| |
| <p>Avatica server allows users to plugin their Custom Authentication |
| mechanism through the HTTPServer Builder. This is useful if users |
| want to combine features of various authentication types. Examples |
| include combining basic authentication with impersonation or adding |
| mutual authentication with impersonation. More Examples are available |
| in <code class="language-plaintext highlighter-rouge">CustomAuthHttpServerTest</code> class.</p> |
| |
| <p>Note: Users need to configure their own <code class="language-plaintext highlighter-rouge">ServerConnectors</code> and |
| <code class="language-plaintext highlighter-rouge">Handlers</code> with the help of <code class="language-plaintext highlighter-rouge">ServerCustomizers</code>.</p> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">AvaticaServerConfiguration</span> <span class="n">configuration</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ExampleAvaticaServerConfiguration</span><span class="o">();</span> |
| <span class="nc">HttpServer</span> <span class="n">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HttpServer</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> |
| <span class="o">.</span><span class="na">withCustomAuthentication</span><span class="o">(</span><span class="n">configuration</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">withPort</span><span class="o">(</span><span class="mi">8765</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">build</span><span class="o">();</span></code></pre></figure> |
| |
| <h2 id="client-implementation">Client implementation</h2> |
| |
| <p>Many HTTP client libraries, such as <a href="https://hc.apache.org/">Apache Commons HttpComponents</a>, already have |
| support for performing Basic, Digest, and SPNEGO authentication. When in doubt, refer to one of |
| these implementations as it is likely correct.</p> |
| |
| <h3 id="spnego">SPNEGO</h3> |
| |
| <p>For information on building SPNEGO support by hand, consult <a href="https://tools.ietf.org/html/rfc4559">RFC-4559</a> |
| which describes how the authentication handshake, through use of the <code class="language-plaintext highlighter-rouge">WWW-Authenticate=Negotiate</code> |
| HTTP header, is used to authenticate a client. Prior to Avatica 1.20.0, this handshake is done |
| for every HTTP call to the Avatica server.</p> |
| |
| <p>Starting in Avatica 1.20.0, Avatica was updated to use a newer version of Jetty which includes |
| the ability to perform one SPNEGO-based authentication handshake but then set a cookie which |
| can be used to re-identify the client without performing subsequent SPNEGO handshakes.</p> |
| |
| <p>This is a notable change because it will effectively reduce the number of HTTP calls that an Avatica |
| client has to make to the server which, for often results in a near 2x performance improvement (as there |
| is a lower-bound of 1’s of milliseconds per HTTP call). However, if the cookie is compromised, another |
| client could potentially access Avatica as the user for whom the cookie was set for. Because of this, it |
| is important to configure the Avatica server to <a href="#tls">use TLS</a> to authenticate its clients.</p> |
| |
| <p>See more information in <a href="https://issues.apache.org/jira/browse/CALCITE-4152">CALCITE-4152</a>.</p> |
| |
| <h3 id="password-based">Password-based</h3> |
| |
| <p>For both HTTP Basic and Digest authentication, the <a href="/avatica/docs/client_reference.html#avatica-user">avatica_user</a> |
| and <a href="/avatica/docs/client_reference.html#avatica-password">avatica_password</a> |
| properties are used to identify the client with the server. If the underlying database |
| (the JDBC driver inside the Avatica server) require their own user and password combination, |
| these are set via the traditional “user” and “password” properties in the Avatica |
| JDBC driver. This also implies that adding HTTP-level authentication in Avatica is likely |
| superfluous.</p> |
| |
| <h2 id="tls">TLS</h2> |
| |
| <p>Deploying the Avatica server with TLS is common practice, like it is for any HTTP server. To do this, |
| use the method <code class="language-plaintext highlighter-rouge">withTls(File, String, File, String)</code> to provide the server’s TLS private key (a.k.a keystore) |
| and the certificate authority’s public key (a.k.a. truststore) as a Java Key Store (JKS) files, along with |
| passwords to validate that the JKS files have not been tampered with.</p> |
| |
| <figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">HttpServer</span> <span class="n">server</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HttpServer</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> |
| <span class="o">.</span><span class="na">withTLS</span><span class="o">(</span><span class="k">new</span> <span class="nc">File</span><span class="o">(</span><span class="s">"/avatica/server.jks"</span><span class="o">),</span> <span class="s">"MyKeystorePassword"</span><span class="o">,</span> |
| <span class="k">new</span> <span class="nf">File</span><span class="o">(</span><span class="s">"/avatica/truststore.jks"</span><span class="o">),</span> <span class="s">"MyTruststorePassword"</span><span class="o">)</span> |
| <span class="o">.</span><span class="na">build</span><span class="o">();</span></code></pre></figure> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <div class="section-nav"> |
| <div class="left align-right"> |
| |
| |
| |
| <a href="/avatica/docs/howto.html" class="prev">Previous</a> |
| |
| </div> |
| <div class="right align-left"> |
| |
| |
| |
| |
| |
| <a href="/avatica/docs/compatibility.html" class="next">Next</a> |
| |
| </div> |
| </div> |
| <div class="clear"></div> |
| |
| |
| </article> |
| </div> |
| |
| <div class="unit one-fifth hide-on-mobiles"> |
| <aside> |
| |
| <h4>Overview</h4> |
| |
| |
| <ul> |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/index.html">Background</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/roadmap.html">Roadmap</a></li> |
| |
| |
| </ul> |
| |
| |
| <h4>Avatica Reference</h4> |
| |
| |
| <ul> |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/client_reference.html">Client Reference</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/json_reference.html">JSON Reference</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/protobuf_reference.html">Protobuf Reference</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/howto.html">HOWTO</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="current"><a href="/avatica/docs/security.html">Security</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/compatibility.html">Compatibility</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/custom_client_artifacts.html">Custom Client Artifacts</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/docker.html">Docker Images</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/protocol_testing.html">Protocol Testing</a></li> |
| |
| |
| </ul> |
| |
| |
| <h4>Avatica Go Client Reference</h4> |
| |
| |
| <ul> |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/go_client_reference.html">Go Client Reference</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/go_howto.html">HOWTO</a></li> |
| |
| |
| </ul> |
| |
| |
| <h4>Avatica Meta</h4> |
| |
| |
| <ul> |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/history.html">History</a></li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/api/">API</a></li> |
| |
| |
| </ul> |
| |
| |
| <h4>Avatica Go Client Meta</h4> |
| |
| |
| <ul> |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class=""><a href="/avatica/docs/go_history.html">Go Client History</a></li> |
| |
| |
| </ul> |
| |
| |
| </aside> |
| </div> |
| |
| |
| <div class="clear"></div> |
| |
| </div> |
| </section> |
| |
| |
| <footer role="contentinfo"> |
| <div id="poweredby"> |
| <a href="http://www.apache.org/"> |
| <span class="sr-only">Apache</span> |
| <img src="/avatica/img/feather.png" width="190" height="77" alt="Apache Logo"></a> |
| </div> |
| <div id="copyright"> |
| <p>The contents of this website are © 2022 |
| <a href="https://www.apache.org/">Apache Software Foundation</a> |
| under the terms of |
| the <a href="https://www.apache.org/licenses/LICENSE-2.0.html"> |
| Apache License v2</a>. Apache Calcite and its logo are |
| trademarks of the Apache Software Foundation. |
| </p> |
| <p> |
| <a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a> |
| </p> |
| </div> |
| </footer> |
| |
| <script> |
| var anchorForId = function (id) { |
| var anchor = document.createElement("a"); |
| anchor.className = "header-link"; |
| anchor.href = "#" + id; |
| anchor.innerHTML = "<span class=\"sr-only\">Permalink</span><i class=\"fa fa-link\"></i>"; |
| anchor.title = "Permalink"; |
| return anchor; |
| }; |
| |
| var linkifyAnchors = function (level, containingElement) { |
| var headers = containingElement.getElementsByTagName("h" + level); |
| for (var h = 0; h < headers.length; h++) { |
| var header = headers[h]; |
| |
| if (typeof header.id !== "undefined" && header.id !== "") { |
| header.appendChild(anchorForId(header.id)); |
| } |
| } |
| }; |
| |
| document.onreadystatechange = function () { |
| if (this.readyState === "complete") { |
| var contentBlock = document.getElementsByClassName("docs")[0] || document.getElementsByClassName("news")[0]; |
| if (!contentBlock) { |
| return; |
| } |
| for (var level = 1; level <= 6; level++) { |
| linkifyAnchors(level, contentBlock); |
| } |
| } |
| }; |
| </script> |
| |
| |
| </body> |
| </html> |