blob: 7d967c35ad99c5f0a57a3e8186a2469ab55f493d [file] [log] [blame]
<noautolink>
[[index][::Go back to Oozie Documentation Index::]]
---+!! Creating Custom Authentication
%TOC%
---++ Hadoop-Auth Authentication Interfaces and classes
1. =org.apache.hadoop.security.authentication.client.Authenticator:= Interface for client authentication mechanisms.
The following authenticators are provided in hadoop-auth:
* KerberosAuthenticator : the authenticator implements the Kerberos SPNEGO authentication sequence.
* PseudoAuthenticator : the authenticator implementation provides an authentication equivalent to Hadoop's Simple
authentication, it trusts the value of the 'user.name' Java System property.
2. =org.apache.hadoop.security.authentication.server.AuthenticationHandler:= Interface for server authentication mechanisms.
* KerberosAuthenticationHandler : the authenticator handler implements the Kerberos SPNEGO authentication mechanism for HTTP.
* AltKerberosAuthenticationHandler: the authenticator handler allows for Kerberos SPNEGO authentication for non-browsers and an alternate form of authentication for browsers. A subclass must implement the alternate authentication (see [[ENG_Custom_Authentication#LoginServerExample][Example Login Server]])
* PseudoAuthenticationHandler : the authenticator handler provides a pseudo authentication mechanism that accepts the user
name specified as a query string parameter.
3. =org.apache.hadoop.security.authentication.server.AuthenticationFilter:= A servlet filter enables protecting web application
resources with different authentication mechanisms provided by AuthenticationHandler. To enable the filter, web application
resources file (ex. web.xml) needs to include a filter class derived from =AuthenticationFilter=.
For more information have a look at the appropriate
[[https://hadoop.apache.org/docs/r2.7.2/hadoop-auth/index.html][Hadoop documentation]].
---++ Provide Custom Authentication to Oozie Client
Apache Oozie contains a default class =org.apache.oozie.client.AuthOozieClient= to support Kerberos HTTP SPNEGO authentication,
pseudo/simple authentication and anonymous access for client connections.
To provide other authentication mechanisms, an Oozie client should extend from =AuthOozieClient= and provide the following
methods should be overridden by derived classes to provide custom authentication:
* getAuthenticator() : return corresponding Authenticator based on value specified by user at =auth= command option.
* createConnection() : create a singleton class at Authenticator to allow client set and get key-value configuration for
authentication.
---++ Provide Custom Authentication to Oozie Server
To accept custom authentication in Oozie server, a filter extends from AuthenticationFilter must be provided. This filter
delegates to the configured authentication handler for authentication and once it obtains an =AuthenticationToken= from it, sets
a signed HTTP cookie with the token. If HTTP cookie is provided with different key name, its cookie value can be retrieved by
overriding =getToken()= method. Please note, only when =getToken()= return NULL, a custom authentication can be invoked and
processed in =AuthenticationFilter.doFilter()=.
The following method explains how to read it and return NULL token.
<verbatim>
protected AuthenticationToken getToken(HttpServletRequest request) throws IOException, AuthenticationException {
String tokenStr = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(AuthenticatedURL.AUTH_COOKIE)) {
tokenStr = cookie.getValue();
LOG.info("Got 'hadoop.auth' cookie from request = " + tokenStr);
if (tokenStr != null && !tokenStr.trim().isEmpty()) {
AuthenticationToken retToken = super.getToken(request);
return retToken;
}
} else if (cookie.getName().equals("NEWAUTH")) {
tokenStr = cookie.getValue();
// DO NOT return the token string so request can authenticated.
}
}
}
return null;
}
</verbatim>
#LoginServerExample
---++ Login Server Example
---+++ Overview
The Login Server Example is a web application that is an example of how to create a login server for Oozie. It provides two example
servlets: LoginServlet and LDAPLoginServlet. The LoginServlet example is very primitive and simply authenticates users whose
username and password match (e.g. user=foo and pass=foo). The LDAPLoginServlet example can be configured against an LDAP server to
authenticate users from that LDAP server. Once authenticated, both example servlets write the username to a cookie that Oozie
checks via the ExampleAltAuthenticationHandler (which uses that cookie for authentication for browsers but Kerberos otherwise).
The LoginServlet and LDAPLoginServlet are run from a separate WAR file called oozie-login.war; its web.xml can be used to configure
which servlet is used as well as some additional properties. The ExampleAltAuthenticationHandler is run as part of the Oozie server
but is built as a separate jar: oozie-login.jar.
---+++ ExampleAltAuthenticationHandler
This is a subclass of the abstract AltKerberosAuthenticationHandler, which is an AuthenticationHandler that allows for a "mixed"
mode of authentication. When a non-browser is used, Kerberos will be used for authentication; when a browser is used, some other
authentication method will be used. In the case of ExampleAltAuthenticationHandler, the other authentication method is to look for
a cookie named =oozie.web.login.auth= and create an AuthenticationToken using the value of the cookie as the username. If the
cookie cannot be found, it will redirect the browser to a page where the user can (presumably) login to a server that can
authenticate the user and create the cookie. As this is obviously a very primitive method of authentication that is not secure, it
should NOT be used in production; it is only provided as an example of how the AltKerberosAuthenticationHandler can be used.
To reiterate: %RED%ExampleAltAuthenticationHandler IS NOT SECURE -- DO NOT USE IT IN A PRODUCTION ENVIRONMENT%ENDCOLOR%
To use the ExampleAltAuthenticationHandler, make at least the following two changes to your oozie-site.xml. All of the existing
Kerberos-related settings are still applicable (for when a non-browser is used) so make sure to configure them appropriately.
<verbatim>
<property>
<name>oozie.authentication.type</name>
<value>org.apache.oozie.authentication.ExampleAltAuthenticationHandler</value>
</property>
<property>
<name>oozie.service.HadoopAccessorService.kerberos.enabled</name>
<value>true</value>
</property>
</verbatim>
Note: The ExampleAltAuthenticationHandler is included in the oozie-login.jar file and not normally included with Oozie core.
Additionally, you can configure which user-agents AltKerberosAuthenticationHandler (and thus ExampleAltAuthenticationHandler)
consider to be non-browsers by setting the following property in oozie-site.xml to a comma separated list. When any of the values
in this property are contained in the user-agent of the request, Kerberos will be used; otherwise, the alternate authentication will
be used.
<verbatim>
<property>
<name>oozie.authentication.alt-kerberos.non-browser.user-agents</name>
<value>java,curl,wget,perl</value>
</property>
</verbatim>
The above values, which are the default, will cause a user-agent such as "java" (the user-agent used by Java programs) to use
Kerberos. Note that this would also match with user-agents such as "java6" and "I am not a JaVa program".
When the ExampleAltAuthenticationHandler cannot find the =oozie.web.login.auth= cookie, it will redirect the user to another URL,
which can be configured by setting the following property in oozie-site.xml. Typically, this URL should take the user to a server
where they can login to acquire the cookie and then get redirected back to the Oozie web console (the Login Server Example does this
and will be explained in more detail later).
<verbatim>
<property>
<name>oozie.authentication.ExampleAltAuthenticationHandler.redirect.url</name>
<value>http://localhost:11000/oozie-login/?backurl={0}</value>
</property>
</verbatim>
The above value, which is the default, will cause the user to be redirected to the Login Server Example if its running in the same
tomcat as Oozie and on the default port. If ={0}= appears anywhere in this URL, it will be replaced by the URL of Oozie's web
console so that the Login Server Example can know where to send the user back while staying independent of Oozie.
---+++ LoginServlet
This is a web servlet that gets bundled in the oozie-login.war web application. It is a very primitive example of a login server
implementation that is compatible with the ExampleAltAuthenticationHandler. When users visit this servlet, they are shown a simple
login page that allows them to enter their username and password. It authenticates them if their username and password are the same
(e.g. user=foo and pass=foo), which is not secure and should not be used in production; it is only provided as an example.
To reiterate: %RED%LoginServlet IS NOT SECURE -- DO NOT USE IT IN A PRODUCTION ENVIRONMENT%ENDCOLOR%
Sending it a GET request returns the login page; the =backurl= parameter is required (so it knows where to redirect the user back to
once they are authenticated), but there is also an optional =username= parameter that will pre-populate the username field if given.
Sending it a POST request will also return the login page, but only if an error occurs (e.g. invalid username or password). As with
the GET request, the =backurl= parameter is required, but now the =username= and =password= parameters are also required. If they
match, the LoginServlet will write the =oozie.web.login.auth= cookie containing the username and redirect the user to the =backurl=,
which is presumably the Oozie web console.
The login page can be configured to look differently by changing the following parameter in the web.xml in the oozie-login.war file
(or in the login/src/main/webapp/WEB-INF/ directory before building it). The file needs to be located in the
login/src/main/resources/ directory and should contain ={0}= for where an error message can go, ={1}= for where the username
included with a GET request will go, and ={2}= for where the =backurl= goes.
<verbatim>
<init-param>
<param-name>login.page.template</param-name>
<param-value>login-page-template.html</param-value>
</init-param>
</verbatim>
The above value, which is the default, is a basic html page that has fields for the username and password and meets the previously
stated requirements.
The =oozie.web.login.auth= cookie will expire 3 minutes after being given to the user. Once the user has been redirected back to
the Oozie web console and given the AuthenticationToken, the =oozie.web.login.auth= cookie is no longer used. If the
AuthenticationToken expires but the user still has a valid =oozie.web.login.auth= cookie, the ExampleAltAuthenticationHandler will
simply give out a new AuthenticationToken; the desired behavior is that the user is bounced back to the oozie-login.war server to
re-authenticate, hence the very short lifetime of the =oozie.web.login.auth= cookie. However, the expiration time of the cookie
is configurable by changing the following parameter in the web.xml in the oozie-login.war file (or in the
login/src/main/webapp/WEB-INF/ directory before building it). It is given in seconds. A positive value indicates that the cookie
will expire after that many seconds have passed; make sure this value is high enough to allow the user to be forwarded to the
backurl before the cookie expires. A negative value indicates that the cookie will be deleted when the browser exits.
<verbatim>
<init-param>
<param-name>login.auth.cookie.expire.time</param-name>
<param-value>180</param-value>
</init-param>
</verbatim>
The above value, which is the default, is the number of seconds in 3 minutes.
---+++ LDAPLoginServlet
This is a second web servlet that gets bundled in the oozie-login.war web application. It inherits from the LoginServlet, so the
previous configuration information (e.g. login.page.template) still applies to this servlet. The only difference between the
LDAPLoginServlet and the LoginServlet, is that the LDAPLoginServlet is configured against an LDAP server to provide the
authentication instead of simply checking that the username and password are equal. As before, this is not secure and should not be
used in production; it is only provided as an example.
To reiterate: %RED%LDAPLoginServlet IS NOT SECURE -- DO NOT USE IT IN A PRODUCTION ENVIRONMENT%ENDCOLOR%
The oozie-login.war web application is configured to use LoginServlet by default. To switch it to use the LDAPLoginServlet, you
have to change the following line in the web.xml from:
<verbatim>
<servlet-class>org.apache.oozie.servlet.login.LoginServlet</servlet-class>
</verbatim>
to:
<verbatim>
<servlet-class>org.apache.oozie.servlet.login.LDAPLoginServlet</servlet-class>
</verbatim>
There are three additional parameters related to LDAP that you should configure in the web.xml:
<verbatim>
<init-param>
<param-name>ldap.provider.url</param-name>
<param-value>ldap://localhost:389</param-value>
</init-param>
<init-param>
<param-name>ldap.context.factory</param-name>
<param-value>com.sun.jndi.ldap.LdapCtxFactory</param-value>
</init-param>
<init-param>
<param-name>ldap.security.authentication</param-name>
<param-value>simple</param-value>
</init-param>
</verbatim>
The ldap.provider.url is the LDAP provider URL to use, the ldap.context.factory is the LDAP context factory to use, and the
ldap.security.authentication is the LDAP security authentication type to use.
---+++ Building and Deploying
The README.txt file in the =login= directory contains instructions on how to build and deploy the Login Server Example
[[index][::Go back to Oozie Documentation Index::]]
</noautolink>