You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oozie.apache.org by rk...@apache.org on 2012/12/01 00:09:37 UTC
svn commit: r1415882 - in /oozie/trunk: ./
core/src/main/java/org/apache/oozie/test/
core/src/test/java/org/apache/oozie/test/ distro/ docs/src/site/twiki/
hadooplibs/hadoop-3/ login/ login/src/ login/src/main/ login/src/main/java/
login/src/main/java/...
Author: rkanter
Date: Fri Nov 30 23:09:35 2012
New Revision: 1415882
URL: http://svn.apache.org/viewvc?rev=1415882&view=rev
Log:
OOZIE-1103 Create example using AltKerberosAuthenticationHandler (rkanter)
Added:
oozie/trunk/login/
oozie/trunk/login/README.txt
oozie/trunk/login/pom.xml
oozie/trunk/login/src/
oozie/trunk/login/src/main/
oozie/trunk/login/src/main/java/
oozie/trunk/login/src/main/java/org/
oozie/trunk/login/src/main/java/org/apache/
oozie/trunk/login/src/main/java/org/apache/oozie/
oozie/trunk/login/src/main/java/org/apache/oozie/authentication/
oozie/trunk/login/src/main/java/org/apache/oozie/authentication/AltKerberosAuthenticationHandler.java
oozie/trunk/login/src/main/java/org/apache/oozie/authentication/ExampleAltAuthenticationHandler.java
oozie/trunk/login/src/main/java/org/apache/oozie/servlet/
oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/
oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LDAPLoginServlet.java
oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LoginServlet.java
oozie/trunk/login/src/main/resources/
oozie/trunk/login/src/main/resources/login-page-template.html
oozie/trunk/login/src/main/webapp/
oozie/trunk/login/src/main/webapp/META-INF/
oozie/trunk/login/src/main/webapp/META-INF/context.xml
oozie/trunk/login/src/main/webapp/WEB-INF/
oozie/trunk/login/src/main/webapp/WEB-INF/web.xml
oozie/trunk/login/src/test/
oozie/trunk/login/src/test/java/
oozie/trunk/login/src/test/java/org/
oozie/trunk/login/src/test/java/org/apache/
oozie/trunk/login/src/test/java/org/apache/oozie/
oozie/trunk/login/src/test/java/org/apache/oozie/authentication/
oozie/trunk/login/src/test/java/org/apache/oozie/authentication/TestExampleAltAuthenticationHandler.java
oozie/trunk/login/src/test/java/org/apache/oozie/servlet/
oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/
oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLDAPLoginServlet.java
oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLoginServlet.java
Modified:
oozie/trunk/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java
oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java
oozie/trunk/distro/pom.xml
oozie/trunk/docs/src/site/twiki/ENG_Custom_Authentication.twiki
oozie/trunk/hadooplibs/hadoop-3/pom.xml
oozie/trunk/pom.xml
oozie/trunk/release-log.txt
oozie/trunk/src/main/assemblies/distro.xml
Modified: oozie/trunk/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java?rev=1415882&r1=1415881&r2=1415882&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java Fri Nov 30 23:09:35 2012
@@ -24,6 +24,7 @@ import org.mortbay.jetty.servlet.Context
import java.net.InetAddress;
import java.net.ServerSocket;
+import java.util.Map;
/**
* An embedded servlet container for testing purposes. <p/> It provides reduced functionality, it supports only
@@ -56,9 +57,25 @@ public class EmbeddedServletContainer {
* @param servletPath servlet path for the servlet, it should be prefixed with '/", it may contain a wild card at
* the end.
* @param servletClass servlet class
+ * @param initParams a mapping of init parameters for the servlet, or null
+ */
+ public void addServletEndpoint(String servletPath, Class servletClass, Map<String, String> initParams) {
+ ServletHolder s = new ServletHolder(servletClass);
+ context.addServlet(s, servletPath);
+ if (initParams != null) {
+ s.setInitParameters(initParams);
+ }
+ }
+
+ /**
+ * Add a servlet to the container.
+ *
+ * @param servletPath servlet path for the servlet, it should be prefixed with '/", it may contain a wild card at
+ * the end.
+ * @param servletClass servlet class
*/
public void addServletEndpoint(String servletPath, Class servletClass) {
- context.addServlet(new ServletHolder(servletClass), servletPath);
+ addServletEndpoint(servletPath, servletClass, null);
}
/**
Modified: oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java?rev=1415882&r1=1415881&r2=1415882&view=diff
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java (original)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/test/XTestCase.java Fri Nov 30 23:09:35 2012
@@ -61,6 +61,7 @@ import org.apache.oozie.store.StoreExcep
import org.apache.oozie.util.IOUtils;
import org.apache.oozie.util.ParamChecker;
import org.apache.oozie.util.XLog;
+import org.junit.Assert;
/**
* Base JUnit <code>TestCase</code> subclass used by all Oozie testcases.
@@ -253,6 +254,12 @@ public abstract class XTestCase extends
File source = (customOozieSite.startsWith("/"))
? new File(customOozieSite) : new File(OOZIE_SRC_DIR, customOozieSite);
source = source.getAbsoluteFile();
+ // If we can't find it, try using the class loader (useful if we're using XTestCase from outside core)
+ if (!source.exists()) {
+ source = new File(getClass().getClassLoader().getResource(oozieTestDB + "-oozie-site.xml").getPath());
+ source = source.getAbsoluteFile();
+ }
+ // If we still can't find it, then exit
if (!source.exists()) {
System.err.println();
System.err.println(XLog.format("Custom configuration file for testing does no exist [{0}]",
Modified: oozie/trunk/distro/pom.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/distro/pom.xml?rev=1415882&r1=1415881&r2=1415882&view=diff
==============================================================================
--- oozie/trunk/distro/pom.xml (original)
+++ oozie/trunk/distro/pom.xml Fri Nov 30 23:09:35 2012
@@ -139,6 +139,21 @@
</dependency>
</dependencies>
</profile>
+ <profile>
+ <id>loginServerExample</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-login</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ <type>war</type>
+ </dependency>
+ </dependencies>
+ </profile>
</profiles>
</project>
Modified: oozie/trunk/docs/src/site/twiki/ENG_Custom_Authentication.twiki
URL: http://svn.apache.org/viewvc/oozie/trunk/docs/src/site/twiki/ENG_Custom_Authentication.twiki?rev=1415882&r1=1415881&r2=1415882&view=diff
==============================================================================
--- oozie/trunk/docs/src/site/twiki/ENG_Custom_Authentication.twiki (original)
+++ oozie/trunk/docs/src/site/twiki/ENG_Custom_Authentication.twiki Fri Nov 30 23:09:35 2012
@@ -19,6 +19,7 @@ The following authenticators are provide
* KerberosAuthenticationHandler : the authenticator handler implements the Kerberos SPNEGO authentication mechanism for HTTP.
* PseudoAuthenticationHandler : the authenticator handler provides a pseudo authentication mechanism that accepts the user name specified as a query string parameter.
+ * 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]])
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 the a filter class derived from =AuthenticationFilter=.
@@ -140,6 +141,144 @@ protected AuthenticationToken getToken(H
}
</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>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.
+
+---+++ 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 (i.e. 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>
+to:
+ <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>
\ No newline at end of file
Modified: oozie/trunk/hadooplibs/hadoop-3/pom.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/hadooplibs/hadoop-3/pom.xml?rev=1415882&r1=1415881&r2=1415882&view=diff
==============================================================================
--- oozie/trunk/hadooplibs/hadoop-3/pom.xml (original)
+++ oozie/trunk/hadooplibs/hadoop-3/pom.xml Fri Nov 30 23:09:35 2012
@@ -38,6 +38,16 @@
<artifactId>hadoop-client</artifactId>
<version>3.0.0-SNAPSHOT</version>
<scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>jasper-runtime</artifactId>
+ <groupId>tomcat</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>jsp-api</artifactId>
+ <groupId>javax.servlet.jsp</groupId>
+ </exclusion>
+ </exclusions>
</dependency>
</dependencies>
Added: oozie/trunk/login/README.txt
URL: http://svn.apache.org/viewvc/oozie/trunk/login/README.txt?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/README.txt (added)
+++ oozie/trunk/login/README.txt Fri Nov 30 23:09:35 2012
@@ -0,0 +1,118 @@
+
+Login Server Example
+====================
+
+---------------------------------
+What is the Login Server Example?
+---------------------------------
+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. Onces 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 Oozie.
+
+More details on the Login Server Example and the three classes can be found on the "Creating Custom Authentication" page of the
+Oozie Documentation.
+
+ExampleAltAuthenticationHandler, LoginServlet, and LDAPLoginServlet ARE NOT SECURE
+ -- THEY SHOULD NOT BE USED IN A PRODUCTION ENVIRONMENT
+
+--------------------------------------------------------------------------------------
+How to build and launch the Login Server Example as part of entire oozie package build
+--------------------------------------------------------------------------------------
+
+1. run mkdistro.sh on top-level directory
+---------------------
+bin/mkdistro.sh -P loginServerExample
+---------------------
+[NOTE]
+The Login Server Example is not included in the build by default, hence the need to specify a maven profile (-P loginServerExample).
+This maven profile causes two additional files to be built: oozie-login.war (contains the oozie login server example) and
+oozie-login.jar (contains the AuthenticationHandler to use with the oozie login server example)
+
+2. move to output directory
+--------------------
+cd distro/target/oozie-<version>-distro/oozie-<version>
+--------------------
+
+3-(a). copy the war file to oozie-server/webapps/
+--------------------
+cp oozie-login.war ./oozie-server/webapps
+--------------------
+[NOTE]
+Method (a) only gives you the login server; to also make the AuthenticationHandler available to the Oozie server, use method (b)
+
+or
+
+3-(b). create /libext and copy the war and jar files to it
+--------------------
+mkdir libext
+cp oozie-login.war ./libext
+cp oozie-login.jar ./libext
+--------------------
+[NOTE]
+bin/oozie-setup.sh is implemented such that oozie-login.war is automatically picked up and deployed to oozie server
+
+4. start oozie server (using bin/oozie-setup.sh and bin/oozie-start.sh) and check through browser
+---------------------
+http://localhost:11000/oozie-login
+---------------------
+[NOTE]
+Using default port number, which is 11000. Tomcat server may fail to start if another application already using the same port.
+Please make sure the port is not being used.
+
+
+---------------------------------------------------------------------------
+How to build and launch Login Server Example only (not whole package build)
+---------------------------------------------------------------------------
+This is to launch the Login Server Example using a web server that you are already running (without using bundled tomcat).
+This is suitable for when you want to host this application on the existing tomcat instance. You need to copy the war file into
+the webapp directory of the existing tomcat.
+
+1. build the Login Server Example and create war file
+---------------------
+// Assuming you are at the top level directory
+mvn clean package -P loginServerExample -Dtest=TestExampleAltAuthenticationHandler,TestLoginServlet,TestLDAPLoginServlet
+---------------------
+[NOTE]
+This must be done from the top level directory because oozie-core is a dependency on the Login Server Example. To skip all tests,
+replace the -Dtest=... with -DskipTests.
+
+2. copy war file to webapps directory of web server
+---------------------
+cp login/target/oozie-login.war <webserver-installed-directory>/webapps/
+---------------------
+
+3. start web server
+---------------------
+<webserver-installed-directory>/bin/startup.sh
+---------------------
+[NOTE]
+name of start script might be different in your web-server, please change accordingly
+
+4. check through browser
+---------------------
+http://localhost:8080/oozie-login
+---------------------
+[NOTE]
+port number might not be 8080 in your web-server setting (usually it's default in tomcat), please change accordingly
+
+5. stop web server
+---------------------
+<webserver-installed-directory>/bin/shutdown.sh
+---------------------
+[NOTE] name of shutdown script might be different in your web-server, please change accordingly
+
+
+=====================================================================
+
+If you have any questions/issues, please send an email to:
+
+user@oozie.apache.org
+
+Subscribe using the link:
+
+http://oozie.apache.org/mail-lists.html
Added: oozie/trunk/login/pom.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/login/pom.xml?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/pom.xml (added)
+++ oozie/trunk/login/pom.xml Fri Nov 30 23:09:35 2012
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-main</artifactId>
+ <version>3.4.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-login</artifactId>
+ <version>3.4.0-SNAPSHOT</version>
+ <description>Apache Oozie Login</description>
+ <name>Apache Oozie Login</name>
+ <packaging>war</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-core</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-auth</artifactId>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-hadoop</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <!-- ApacheDS needed for LDAP unit tests -->
+ <dependency>
+ <groupId>org.apache.directory.server</groupId>
+ <artifactId>apacheds-server-unit</artifactId>
+ <version>1.0.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-hadoop-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>oozie-login</finalName>
+ <plugins>
+ <!-- Make the oozie-login.jar too -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>make-a-jar</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludeSubProjects>false</excludeSubProjects>
+ <excludes>
+ <!-- excluding all as the root POM does the full check-->
+ <exclude>**</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptors>
+ <descriptor>../src/main/assemblies/empty.xml</descriptor>
+ </descriptors>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
+
Added: oozie/trunk/login/src/main/java/org/apache/oozie/authentication/AltKerberosAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/main/java/org/apache/oozie/authentication/AltKerberosAuthenticationHandler.java?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/main/java/org/apache/oozie/authentication/AltKerberosAuthenticationHandler.java (added)
+++ oozie/trunk/login/src/main/java/org/apache/oozie/authentication/AltKerberosAuthenticationHandler.java Fri Nov 30 23:09:35 2012
@@ -0,0 +1,137 @@
+/**
+ * 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.
+ */
+package org.apache.oozie.authentication;
+
+import java.io.IOException;
+import java.util.Properties;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.hadoop.security.authentication.server.AuthenticationToken;
+import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
+
+// TODO: Delete this class when hadoop's AltKerberosAuthenticationHandler becomes available in a hadoop release
+/**
+ * The {@link AltKerberosAuthenticationHandler} behaves exactly the same way as the KerberosAuthenticationHandler, except that it
+ * allows for an alternative form of authentication for browsers while still using Kerberos for Java access. This is an abstract
+ * class that should be subclassed to allow a developer to implement their own custom authentication for browser access. The
+ * alternateAuthenticate method will be called whenever a request comes from a browser.
+ * <p/>
+ */
+public abstract class AltKerberosAuthenticationHandler extends KerberosAuthenticationHandler {
+
+ /**
+ * Constant that identifies the authentication mechanism.
+ */
+ public static final String TYPE = "alt-kerberos";
+
+ /**
+ * Constant for the configuration property that indicates which user agents are not considered browsers (comma separated)
+ */
+ public static final String NON_BROWSER_USER_AGENTS = TYPE + ".non-browser.user-agents";
+ private static final String NON_BROWSER_USER_AGENTS_DEFAULT = "java,curl,wget,perl";
+
+ private String[] nonBrowserUserAgents;
+
+ /**
+ * Returns the authentication type of the authentication handler, 'alt-kerberos'.
+ * <p/>
+ *
+ * @return the authentication type of the authentication handler, 'alt-kerberos'.
+ */
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public void init(Properties config) throws ServletException {
+ super.init(config);
+
+ nonBrowserUserAgents = config.getProperty(NON_BROWSER_USER_AGENTS, NON_BROWSER_USER_AGENTS_DEFAULT).split("\\W*,\\W*");
+ for (int i = 0; i < nonBrowserUserAgents.length; i++) {
+ nonBrowserUserAgents[i] = nonBrowserUserAgents[i].toLowerCase();
+ }
+ }
+
+ /**
+ * It enforces the the Kerberos SPNEGO authentication sequence returning an {@link AuthenticationToken} only after the Kerberos
+ * SPNEGO sequence has completed successfully (in the case of Java access) and only after the custom authentication implemented
+ * by the subclass in alternateAuthenticate has completed successfully (in the case of browser access).
+ * <p/>
+ *
+ * @param request the HTTP client request.
+ * @param response the HTTP client response.
+ *
+ * @return an authentication token if the request is authorized or null
+ *
+ * @throws IOException thrown if an IO error occurred
+ * @throws AuthenticationException thrown if an authentication error occurred
+ */
+ @Override
+ public AuthenticationToken authenticate(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, AuthenticationException {
+ AuthenticationToken token;
+ if (isBrowser(request.getHeader("User-Agent"))) {
+ token = alternateAuthenticate(request, response);
+ }
+ else {
+ token = super.authenticate(request, response);
+ }
+ return token;
+ }
+
+ /**
+ * This method parses the User-Agent String and returns whether or not it refers to a browser. If its not a browser, then
+ * Kerberos authentication will be used; if it is a browser, alternateAuthenticate from the subclass will be used.
+ * <p/>
+ * A User-Agent String is considered to be a browser if it does not contain any of the values from
+ * alt-kerberos.non-browser.user-agents; the default behavior is to consider everything a browser unless it contains one of:
+ * "java", "curl", "wget", or "perl". Subclasses can optionally override this method to use different behavior.
+ *
+ * @param userAgent The User-Agent String, or null if there isn't one
+ * @return true if the User-Agent String refers to a browser, false if not
+ */
+ protected boolean isBrowser(String userAgent) {
+ if (userAgent == null) {
+ return false;
+ }
+ userAgent = userAgent.toLowerCase();
+ boolean isBrowser = true;
+ for (String nonBrowserUserAgent : nonBrowserUserAgents) {
+ if (userAgent.contains(nonBrowserUserAgent)) {
+ isBrowser = false;
+ break;
+ }
+ }
+ return isBrowser;
+ }
+
+ /**
+ * Subclasses should implement this method to provide the custom authentication to be used for browsers.
+ *
+ * @param request the HTTP client request.
+ * @param response the HTTP client response.
+ * @return an authentication token if the request is authorized, or null
+ * @throws IOException thrown if an IO error occurs
+ * @throws AuthenticationException thrown if an authentication error occurs
+ */
+ public abstract AuthenticationToken alternateAuthenticate(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, AuthenticationException;
+}
Added: oozie/trunk/login/src/main/java/org/apache/oozie/authentication/ExampleAltAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/main/java/org/apache/oozie/authentication/ExampleAltAuthenticationHandler.java?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/main/java/org/apache/oozie/authentication/ExampleAltAuthenticationHandler.java (added)
+++ oozie/trunk/login/src/main/java/org/apache/oozie/authentication/ExampleAltAuthenticationHandler.java Fri Nov 30 23:09:35 2012
@@ -0,0 +1,127 @@
+/**
+ * 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.
+ */
+package org.apache.oozie.authentication;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.text.MessageFormat;
+import java.util.Properties;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+// TODO: Switch to subclassing hadoop's AltKerberosAuthenticationHandler when it becomes available in a hadoop release
+//import org.apache.hadoop.security.authentication.server.AltKerberosAuthenticationHandler;
+import org.apache.hadoop.security.authentication.server.AuthenticationToken;
+import org.apache.oozie.service.Services;
+
+/**
+ * This class provides an implementation of the {@link AltKerberosAuthenticationHandler} as a simple example. It is meant to be
+ * used with the Login Server Example. The alternate authentication offered by this class is to check for a cookie named
+ * "oozie.web.login.auth" and use its value as the username. More information can be found in the README.txt for the Login Server
+ * Example. Note that this implementation is NOT SECURE and should not be used in production.
+ */
+public class ExampleAltAuthenticationHandler extends AltKerberosAuthenticationHandler {
+
+ /**
+ * Constant for the configuration property that indicates the redirect URL to send unauthenticated users to the Login Server.
+ * It can include {0}, which will be replaced by the Oozie web console URL.
+ */
+ private static final String REDIRECT_URL = "oozie.authentication.ExampleAltAuthenticationHandler.redirect.url";
+ private static final String REDIRECT_URL_DEFAULT = "http://localhost:11000/oozie-login/?backurl={0}";
+
+ private String redirectURL;
+
+ @Override
+ public void init(Properties config) throws ServletException {
+ super.init(config);
+
+ Configuration conf = Services.get().getConf();
+ redirectURL = conf.get(REDIRECT_URL, REDIRECT_URL_DEFAULT);
+ }
+
+ /**
+ * Implementation of the custom authentication. It looks for the "oozie.web.login.auth" cookie and if it exists, returns an
+ * AuthenticationToken with the cookie's value as the username. Otherwise, it will redirect the user to the login server via
+ * the REDIRECT_URL.
+ *
+ * @param request the HTTP client request.
+ * @param response the HTTP client response.
+ * @return an authentication token if the request is authorized, or null
+ * @throws IOException thrown if an IO error occurs
+ * @throws AuthenticationException thrown if an authentication error occurs
+ */
+ @Override
+ public AuthenticationToken alternateAuthenticate(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, AuthenticationException {
+ AuthenticationToken token = null;
+ Cookie[] cookies = request.getCookies();
+ Cookie authCookie = verifyAndExtractAltAuth(cookies);
+ String altAuthUserName = getAltAuthUserName(authCookie);
+ // Authenticated
+ if (altAuthUserName != null) {
+ token = new AuthenticationToken(altAuthUserName, altAuthUserName, getType());
+ }
+ // Not Authenticated
+ else {
+ StringBuffer sb = request.getRequestURL();
+ if (request.getQueryString() != null) {
+ sb.append("?").append(request.getQueryString());
+ }
+ String url = MessageFormat.format(redirectURL, URLEncoder.encode(sb.toString(), "ISO-8859-1"));
+ url = response.encodeRedirectURL(url);
+ response.sendRedirect(url);
+ }
+ return token;
+ }
+
+ /**
+ * Verifies and extracts the "oozie.web.login.auth" Cookie from the passed in cookies. Note that this implementation doesn't
+ * actually do any verification, but a subclass can override it to do so.
+ *
+ * @param cookies The cookies from a request.
+ * @return The "oozie.web.login.auth" cookie or null
+ */
+ protected Cookie verifyAndExtractAltAuth(Cookie[] cookies) {
+ if (cookies == null) {
+ return null;
+ }
+ for (Cookie cookie : cookies) {
+ if (cookie.getName().equals("oozie.web.login.auth")) {
+ // Here the cookie should be verified for integrity/authenticity from the login service
+ return cookie;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the username from the "oozie.web.login.auth" cookie.
+ *
+ * @param authCookie The "oozie.web.login.auth" cookie
+ * @return The username from the cookie or null if the cookie is null
+ */
+ protected String getAltAuthUserName(Cookie authCookie) {
+ if (authCookie == null) {
+ return null;
+ }
+ return authCookie.getValue();
+ }
+}
Added: oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LDAPLoginServlet.java
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LDAPLoginServlet.java?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LDAPLoginServlet.java (added)
+++ oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LDAPLoginServlet.java Fri Nov 30 23:09:35 2012
@@ -0,0 +1,107 @@
+/**
+ * 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.
+ */
+package org.apache.oozie.servlet.login;
+
+import java.util.Hashtable;
+import javax.naming.Context;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.servlet.ServletException;
+
+/**
+ * This class provides an LDAP example Login Servlet to be used with the ExampleAltAuthenticationHandler. It provides a login page
+ * to the user and checks that the username and password are are able to login to the configured LDAP server and writes the username
+ * to a cookie named "oozie.web.login.auth". Once authenticated, it will send the user to the "backurl". More information can be
+ * found in the README.txt for the Login Server Example. Note that this implementation is NOT SECURE and should not be used in
+ * production.
+ */
+public class LDAPLoginServlet extends LoginServlet {
+
+ /**
+ * Constant for the configuration property that indicates LDAP provider url to use. Note that this is configured in the web.xml
+ * file.
+ */
+ public static final String LDAP_PROVIDER_URL_KEY = "ldap.provider.url";
+ private static final String LDAP_PROVIDER_URL_DEFAULT = "ldap://localhost:389";
+ private String ldapProviderUrl;
+
+ /**
+ * Constant for the configuration property that indicates LDAP context factory to use. Note that this is configured in the
+ * web.xml file.
+ */
+ public static final String LDAP_CONTEXT_FACTORY_KEY = "ldap.context.factory";
+ private static final String LDAP_CONTEXT_FACTORY_DEFAULT = "com.sun.jndi.ldap.LdapCtxFactory";
+ private String ldapContextFactory;
+
+ /**
+ * Constant for the configuration property that indicates LDAP security authentication type to use. Note that this is
+ * configured in the web.xml file.
+ */
+ public static final String LDAP_SECURITY_AUTHENTICATION_KEY = "ldap.security.authentication";
+ private static final String LDAP_SECURITY_AUTHENTICATION_DEFAULT = "simple";
+ private String ldapSecurityAuthentication;
+
+ @Override
+ public void init() throws ServletException {
+ super.init();
+
+ ldapProviderUrl = getInitParameter(LDAP_PROVIDER_URL_KEY);
+ if (ldapProviderUrl == null) {
+ ldapProviderUrl = LDAP_PROVIDER_URL_DEFAULT;
+ }
+
+ ldapContextFactory = getInitParameter(LDAP_CONTEXT_FACTORY_KEY);
+ if (ldapContextFactory == null) {
+ ldapContextFactory = LDAP_CONTEXT_FACTORY_DEFAULT;
+ }
+
+ ldapSecurityAuthentication = getInitParameter(LDAP_SECURITY_AUTHENTICATION_KEY);
+ if (ldapSecurityAuthentication == null) {
+ ldapSecurityAuthentication = LDAP_SECURITY_AUTHENTICATION_DEFAULT;
+ }
+ }
+
+ /**
+ * This method is overridden from LoginServlet to verify the password by attempting to use the username and password to login to
+ * the configured LDAP server.
+ *
+ * @param username The username
+ * @param password The password
+ * @return true if verified, false if not
+ */
+ @Override
+ protected boolean verifyPassword(String username, String password) {
+ boolean result = false;
+ try {
+ Hashtable<String, String> env = new Hashtable<String, String>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, ldapContextFactory);
+ env.put(Context.PROVIDER_URL, ldapProviderUrl);
+ env.put(Context.SECURITY_AUTHENTICATION, ldapSecurityAuthentication);
+ env.put(Context.SECURITY_PRINCIPAL, username);
+ env.put(Context.SECURITY_CREDENTIALS, password);
+ DirContext ctx = new InitialDirContext(env);
+ if (ctx != null) {
+ ctx.close();
+ result = true;
+ }
+ } catch (Exception e) {
+ result = false;
+ }
+ return result;
+ }
+}
Added: oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LoginServlet.java
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LoginServlet.java?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LoginServlet.java (added)
+++ oozie/trunk/login/src/main/java/org/apache/oozie/servlet/login/LoginServlet.java Fri Nov 30 23:09:35 2012
@@ -0,0 +1,153 @@
+/**
+ * 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.
+ */
+package org.apache.oozie.servlet.login;
+
+import java.io.*;
+import java.text.MessageFormat;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This class provides a basic example Login Servlet to be used with the ExampleAltAuthenticationHandler. It provides a login page
+ * to the user and simply checks that the username and password are equal (e.g. user=foo pass=foo) and writes the username to a
+ * cookie named "oozie.web.login.auth". Once authenticated, it will send the user to the "backurl". More information can be found
+ * in the README.txt for the Login Server Example. Note that this implementation is NOT SECURE and should not be used in
+ * production.
+ */
+public class LoginServlet extends HttpServlet {
+
+ /**
+ * Constant for the configuration property that indicates the login page html to use. 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. Note that this is configured in the web.xml file.
+ */
+ public static final String LOGIN_PAGE_TEMPLATE_KEY = "login.page.template";
+ private static final String LOGIN_PAGE_TEMPLATE_DEFAULT = "login-page-template.html";
+ private String loginPageTemplate;
+
+ private static final String USERNAME = "username";
+ private static final String PASSWORD = "password";
+ private static final String BACKURL = "backurl";
+
+ @Override
+ public void init() throws ServletException {
+ // Read in the login page html
+ String loginPageTemplateName = getInitParameter(LOGIN_PAGE_TEMPLATE_KEY);
+ if (loginPageTemplateName == null) {
+ loginPageTemplateName = LOGIN_PAGE_TEMPLATE_DEFAULT;
+ }
+ InputStream is = getClass().getClassLoader().getResourceAsStream(loginPageTemplateName);
+ if (is == null) {
+ throw new ServletException("Could not find resource [" + loginPageTemplateName + "]");
+ }
+ try {
+ StringBuilder sb = new StringBuilder();
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String line = br.readLine();
+ while (line != null) {
+ sb.append(line).append("\n");
+ line = br.readLine();
+ }
+ br.close();
+ loginPageTemplate = sb.toString();
+ } catch (IOException ex) {
+ throw new ServletException("Could not read resource [" + loginPageTemplateName + "]");
+ }
+ }
+
+ protected void renderLoginPage(String message, String username, String backUrl, HttpServletResponse resp)
+ throws ServletException, IOException {
+ resp.setContentType("text/html");
+ Writer writer = resp.getWriter();
+ writer.write(MessageFormat.format(loginPageTemplate, message, username, backUrl));
+ writer.close();
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ // Check for the optional username parameter
+ String username = req.getParameter(USERNAME);
+ if (username == null) {
+ username = "";
+ }
+ // Check for the required backurl parameter
+ String backUrl = req.getParameter(BACKURL);
+ if (backUrl == null || backUrl.trim().isEmpty()) {
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "missing or invalid '" + BACKURL + "' parameter");
+ }
+ else {
+ renderLoginPage("", username, backUrl, resp);
+ }
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ String backUrl = req.getParameter(BACKURL);
+ // Check for the required backurl parameter
+ if (backUrl == null || backUrl.trim().isEmpty()) {
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "missing or invalid '" + BACKURL + "' parameter");
+ } else {
+ // Check for the requried username and password parameters
+ String username = req.getParameter(USERNAME);
+ String password = req.getParameter(PASSWORD);
+ if (username == null || username.trim().isEmpty()) {
+ renderLoginPage("<font color=\"red\">Error: Invalid Username or Password</font><br>", "", backUrl, resp);
+ }
+ else if (password == null || password.trim().isEmpty()) {
+ renderLoginPage("<font color=\"red\">Error: Invalid Username or Password</font><br>", username, backUrl, resp);
+ }
+ // Verify that the username and password are correct
+ else if (verifyPassword(username, password)) {
+ // If so, write the "oozie.web.login.auth" cookie and redirect back to the backurl
+ writeCookie(resp, username);
+ resp.sendRedirect(backUrl);
+ } else {
+ renderLoginPage("<font color=\"red\">Error: Invalid Username or Password</font><br>", username, backUrl, resp);
+ }
+ }
+ }
+
+ /**
+ * Verify that the given username and password are correct. In this implementation, they are correct when they are equal, but
+ * a subclass can override this to provide a more complex/secure mechanism.
+ *
+ * @param username The username
+ * @param password The password
+ * @return true if verified, false if not
+ */
+ protected boolean verifyPassword(String username, String password) {
+ return (username.equals(password));
+ }
+
+ /**
+ * Write the "oozie.web.login.auth" cookie containing the username. A subclass can override this to include more information
+ * into the cookie; though this will likely break compatibility with the ExampleAltAuthenticationHandler, so it would have to
+ * be extended as well.
+ *
+ * @param resp The response
+ * @param username The username
+ */
+ protected void writeCookie(HttpServletResponse resp, String username) {
+ Cookie cookie = new Cookie("oozie.web.login.auth", username);
+ cookie.setPath("/");
+ resp.addCookie(cookie);
+ }
+}
Added: oozie/trunk/login/src/main/resources/login-page-template.html
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/main/resources/login-page-template.html?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/main/resources/login-page-template.html (added)
+++ oozie/trunk/login/src/main/resources/login-page-template.html Fri Nov 30 23:09:35 2012
@@ -0,0 +1,36 @@
+<html>
+<!--
+ 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.
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Oozie Web Console Login</title>
+</head>
+<body>
+<img src="../oozie/oozie_50x.png" height="30"/>
+<form name="input" action="/oozie-login/" method="POST">
+ <fieldset>
+ <legend>Login to Oozie Web Console:</legend>
+ {0}
+ Username: <input type="text" size="30" name="username" value="{1}"><br>
+ Password: <input type="password" size="30" name="password"><br>
+ <input type="hidden" name="backurl" value="{2}">
+ <input type="submit" value="Login">
+ </fieldset>
+</form>
+</body>
+</html>
\ No newline at end of file
Added: oozie/trunk/login/src/main/webapp/META-INF/context.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/main/webapp/META-INF/context.xml?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/main/webapp/META-INF/context.xml (added)
+++ oozie/trunk/login/src/main/webapp/META-INF/context.xml Fri Nov 30 23:09:35 2012
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<Context path="/oozie-login">
+</Context>
Added: oozie/trunk/login/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/main/webapp/WEB-INF/web.xml?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/main/webapp/WEB-INF/web.xml (added)
+++ oozie/trunk/login/src/main/webapp/WEB-INF/web.xml Fri Nov 30 23:09:35 2012
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+ <display-name>Oozie Login</display-name>
+
+ <servlet>
+ <servlet-name>login</servlet-name>
+ <display-name>Oozie Login</display-name>
+ <!-- Replace the following with "org.apache.oozie.servlet.login.LDAPLoginServlet" to use LDAP -->
+ <servlet-class>org.apache.oozie.servlet.login.LoginServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+
+ <!-- Uncomment to change the default values
+ <init-param>
+ <param-name>login.page.template</param-name>
+ <param-value>login-page-template.html</param-value>
+ <description>
+ Set the login page template used for both LoginServlet and LDAPLoginServlet. The file needs to be located in the
+ login/src/main/resources/ directory and should contain {0} for where error message go, {1} for where the username
+ included with a GET request goes, and {2} for where the "backurl" goes (redirects the user back to the oozie web
+ console).
+ </description>
+ </init-param>
+ -->
+ <!--
+ <init-param>
+ <param-name>ldap.provider.url</param-name>
+ <param-value>ldap://localhost:389</param-value>
+ <description>The LDAP provider URL for the LDAPLoginServlet</description>
+ </init-param>
+ <init-param>
+ <param-name>ldap.context.factory</param-name>
+ <param-value>com.sun.jndi.ldap.LdapCtxFactory</param-value>
+ <description>The LDAP context factory for the LDAPLoginServlet</description>
+ </init-param>
+ <init-param>
+ <param-name>ldap.security.authentication</param-name>
+ <param-value>simple</param-value>
+ <description>The security authentication type for the LDAPLoginServlet</description>
+ </init-param>
+ -->
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>login</servlet-name>
+ <url-pattern>/</url-pattern>
+ </servlet-mapping>
+
+</web-app>
Added: oozie/trunk/login/src/test/java/org/apache/oozie/authentication/TestExampleAltAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/test/java/org/apache/oozie/authentication/TestExampleAltAuthenticationHandler.java?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/test/java/org/apache/oozie/authentication/TestExampleAltAuthenticationHandler.java (added)
+++ oozie/trunk/login/src/test/java/org/apache/oozie/authentication/TestExampleAltAuthenticationHandler.java Fri Nov 30 23:09:35 2012
@@ -0,0 +1,100 @@
+/**
+ * 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.
+ */
+package org.apache.oozie.authentication;
+
+import java.net.URLEncoder;
+import java.text.MessageFormat;
+import java.util.Properties;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.hadoop.security.authentication.server.AuthenticationToken;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.test.XTestCase;
+import org.mockito.Mockito;
+
+public class TestExampleAltAuthenticationHandler extends XTestCase {
+
+ private ExampleAltAuthenticationHandler handler;
+ private final String redirectUrl = "http://foo:11000/oozie-login/?backurl={0}";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ new Services().init();
+ Services.get().getConf().set("oozie.authentication.ExampleAltAuthenticationHandler.redirect.url", redirectUrl);
+ handler = new ExampleAltAuthenticationHandler();
+ Properties props = new Properties();
+ props.setProperty(ExampleAltAuthenticationHandler.PRINCIPAL, getOoziePrincipal());
+ props.setProperty(ExampleAltAuthenticationHandler.KEYTAB, getKeytabFile());
+ try {
+ handler.init(props);
+ } catch (Exception ex) {
+ handler = null;
+ throw ex;
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (handler != null) {
+ handler.destroy();
+ handler = null;
+ }
+ Services.get().destroy();
+ super.tearDown();
+ }
+
+ public void testRedirect() throws Exception {
+ String oozieBaseUrl = Services.get().getConf().get("oozie.base.url");
+ String resolvedRedirectUrl = MessageFormat.format(redirectUrl, URLEncoder.encode(oozieBaseUrl, "ISO-8859-1"));
+
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
+
+ // A User-Agent without "java", "curl", "wget", or "perl" (default) in it is considered to be a browser
+ Mockito.when(request.getHeader("User-Agent")).thenReturn("Some Browser");
+ // Pretend the request URL is from oozie.base.url
+ Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer(oozieBaseUrl));
+
+ // The HttpServletResponse needs to return the encoded redirect url
+ Mockito.when(response.encodeRedirectURL(resolvedRedirectUrl)).thenReturn(resolvedRedirectUrl);
+
+ handler.authenticate(request, response);
+ Mockito.verify(response).sendRedirect(resolvedRedirectUrl);
+ }
+
+ public void testAuthenticateCookie() throws Exception {
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
+
+ // A User-Agent without "java" in it is considered to be a browser
+ Mockito.when(request.getHeader("User-Agent")).thenReturn("Some Browser");
+
+ // We need the request to return the auth cookie
+ Cookie[] cookies = {new Cookie("some.other.cookie", "someValue"),
+ new Cookie("oozie.web.login.auth", "someUser")};
+ Mockito.when(request.getCookies()).thenReturn(cookies);
+
+ AuthenticationToken token = handler.authenticate(request, response);
+ assertEquals("someUser", token.getUserName());
+ assertEquals("someUser", token.getName());
+ assertEquals("alt-kerberos", token.getType());
+ }
+}
Added: oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLDAPLoginServlet.java
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLDAPLoginServlet.java?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLDAPLoginServlet.java (added)
+++ oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLDAPLoginServlet.java Fri Nov 30 23:09:35 2012
@@ -0,0 +1,165 @@
+/**
+ * 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.
+ */
+package org.apache.oozie.servlet.login;
+
+import java.io.File;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.directory.server.core.configuration.MutablePartitionConfiguration;
+import org.apache.directory.server.unit.AbstractServerTest;
+
+// LDAP stuff based on https://cwiki.apache.org/DIRxSRVx10/using-apacheds-for-unit-tests.html
+// The default admin user for Apache DS is "uid=admin,ou=system" and password is "secret"
+public class TestLDAPLoginServlet extends AbstractServerTest {
+
+ // We need to subclass the AbstractServerTest to get the LDAP stuff, so we'll have to do a wrapper to inherit the
+ // TestLoginServlet tests instead of subclassing it
+ TestLoginServlet tls = new TestLoginServlet() {
+ @Override
+ protected Class getServletClass() {
+ // Make the TestLoginServlet use LDAPLoginServlet instead of LoginServlet
+ return LDAPLoginServlet.class;
+ }
+
+ @Override
+ protected Map<String, String> getInitParameters() {
+ // Configure for LDAP tests
+ HashMap<String, String> initParams = new HashMap<String, String>();
+ initParams.put("ldap.provider.url", "o=test");
+ initParams.put("ldap.context.factory", "org.apache.directory.server.jndi.ServerContextFactory");
+ return initParams;
+ }
+ };
+
+ @Override
+ public void setUp() throws Exception {
+ // Add partition 'test'
+ MutablePartitionConfiguration pcfg = new MutablePartitionConfiguration();
+ pcfg.setName("test");
+ pcfg.setSuffix("o=test");
+
+ // Create some indices
+ Set<String> indexedAttrs = new HashSet<String>();
+ indexedAttrs.add("objectClass");
+ indexedAttrs.add("o");
+ pcfg.setIndexedAttributes(indexedAttrs);
+
+ // Create a first entry associated to the partition
+ Attributes attrs = new BasicAttributes(true);
+
+ // First, the objectClass attribute
+ Attribute attr = new BasicAttribute("objectClass");
+ attr.add("top");
+ attr.add("organization");
+ attrs.put(attr);
+
+ // The the 'Organization' attribute
+ attr = new BasicAttribute("o");
+ attr.add("test");
+ attrs.put(attr);
+
+ // Associate this entry to the partition
+ pcfg.setContextEntry(attrs);
+
+ // As we can create more than one partition, we must store
+ // each created partition in a Set before initialization
+ Set<MutablePartitionConfiguration> pcfgs = new HashSet<MutablePartitionConfiguration>();
+ pcfgs.add(pcfg);
+
+ configuration.setContextPartitionConfigurations(pcfgs);
+
+ // Create a working directory
+ File workingDirectory = new File("server-work");
+ configuration.setWorkingDirectory(workingDirectory);
+
+ // Now, let's call the super class which is responsible for the
+ // partitions creation
+ super.setUp();
+
+ // setUp the TestLoginServlet
+ tls.setUp();
+ }
+
+ public void testGetMissingBackurl() throws Exception {
+ tls.testGetMissingBackurl();
+ }
+
+ public void testGetSuccess() throws Exception {
+ tls.testGetSuccess();
+ }
+
+ public void testPostMissingBackurl() throws Exception {
+ tls.testPostMissingBackurl();
+ }
+
+ public void testPostMissingUsernamePassword() throws Exception {
+ tls.testPostMissingUsernamePassword();
+ }
+
+ public void testPostInvalidUsernamePassword() throws Exception {
+ // Valid username, invalid password
+ URL url = new URL(tls.container.getServletURL("/")
+ + "?backurl=http://foo:11000/oozie&username=uid=admin,ou=system&password=bar");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+ String html = tls.getHTML(conn);
+ assertEquals(MessageFormat.format(TestLoginServlet.loginPageTemplate,
+ "<font color=\"red\">Error: Invalid Username or Password</font><br>",
+ "uid=admin,ou=system", "http://foo:11000/oozie"), html);
+
+ // InValid username, valid password
+ url = new URL(tls.container.getServletURL("/")
+ + "?backurl=http://foo:11000/oozie&username=foo&password=secret");
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+ html = tls.getHTML(conn);
+ assertEquals(MessageFormat.format(TestLoginServlet.loginPageTemplate,
+ "<font color=\"red\">Error: Invalid Username or Password</font><br>", "foo", "http://foo:11000/oozie"), html);
+ }
+
+ public void testPostSuccess() throws Exception {
+ // Now that its actually going to work successfully, the backurl needs to go somewhere real; about:blank provides a
+ // convinient location that doesn't require internet access or another servlet running locally
+ URL url = new URL(tls.container.getServletURL("/") + "?backurl=about:blank&username=uid=admin,ou=system&password=secret");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_FOUND, conn.getResponseCode());
+ String cookies = tls.getCookies(conn);
+ assertTrue(cookies.contains("oozie.web.login.auth=uid=admin,ou=system"));
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ // tear down the TestLoginServlet
+ tls.tearDown();
+
+ super.tearDown();
+ }
+}
Added: oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLoginServlet.java
URL: http://svn.apache.org/viewvc/oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLoginServlet.java?rev=1415882&view=auto
==============================================================================
--- oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLoginServlet.java (added)
+++ oozie/trunk/login/src/test/java/org/apache/oozie/servlet/login/TestLoginServlet.java Fri Nov 30 23:09:35 2012
@@ -0,0 +1,195 @@
+/**
+ * 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.
+ */
+package org.apache.oozie.servlet.login;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletResponse;
+import junit.framework.TestCase;
+import org.apache.oozie.test.EmbeddedServletContainer;
+
+public class TestLoginServlet extends TestCase {
+
+ protected EmbeddedServletContainer container;
+ protected static String loginPageTemplate;
+
+ static {
+ try {
+ StringBuilder sb = new StringBuilder();
+ InputStream is = new FileInputStream(new File("src/main/resources/login-page-template.html"));
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String line = br.readLine();
+ while (line != null) {
+ sb.append(line).append("\n");
+ line = br.readLine();
+ }
+ br.close();
+ loginPageTemplate = sb.toString();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ fail("Unable to read login-page-template.html");
+ }
+ }
+
+ protected Class getServletClass() {
+ return LoginServlet.class;
+ }
+
+ protected Map<String, String> getInitParameters() {
+ return null;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ container = new EmbeddedServletContainer("oozie-login");
+ container.addServletEndpoint("/", getServletClass(), getInitParameters());
+ container.start();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (container != null) {
+ container.stop();
+ }
+ super.tearDown();
+ }
+
+ public void testGetMissingBackurl() throws Exception {
+ URL url = new URL(container.getServletURL("/"));
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+ assertEquals(HttpServletResponse.SC_BAD_REQUEST, conn.getResponseCode());
+ assertEquals("missing or invalid 'backurl' parameter", conn.getResponseMessage());
+ }
+
+ public void testGetSuccess() throws Exception {
+ URL url = new URL(container.getServletURL("/") + "?backurl=http://foo:11000/oozie");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+ assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+ String html = getHTML(conn);
+ assertEquals(MessageFormat.format(loginPageTemplate, "", "", "http://foo:11000/oozie"), html);
+
+ // With optional username parameter
+ url = new URL(container.getServletURL("/") + "?backurl=http://foo:11000/oozie&username=foo");
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+ assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+ html = getHTML(conn);
+ assertEquals(MessageFormat.format(loginPageTemplate, "", "foo", "http://foo:11000/oozie"), html);
+ }
+
+ public void testPostMissingBackurl() throws Exception {
+ // Missing all
+ URL url = new URL(container.getServletURL("/"));
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_BAD_REQUEST, conn.getResponseCode());
+ assertEquals("missing or invalid 'backurl' parameter", conn.getResponseMessage());
+
+ // Missing only backurl
+ url = new URL(container.getServletURL("/") + "?username=foo&password=bar");
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_BAD_REQUEST, conn.getResponseCode());
+ assertEquals("missing or invalid 'backurl' parameter", conn.getResponseMessage());
+ }
+
+ public void testPostMissingUsernamePassword() throws Exception {
+ // Missing password
+ URL url = new URL(container.getServletURL("/") + "?backurl=http://foo:11000/oozie&username=foo");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+ String html = getHTML(conn);
+ assertEquals(MessageFormat.format(loginPageTemplate,
+ "<font color=\"red\">Error: Invalid Username or Password</font><br>", "foo", "http://foo:11000/oozie"), html);
+
+ // Missing username
+ url = new URL(container.getServletURL("/") + "?backurl=http://foo:11000/oozie&password=bar");
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+ html = getHTML(conn);
+ assertEquals(MessageFormat.format(loginPageTemplate,
+ "<font color=\"red\">Error: Invalid Username or Password</font><br>", "", "http://foo:11000/oozie"), html);
+
+ // Missing both
+ url = new URL(container.getServletURL("/") + "?backurl=http://foo:11000/oozie");
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+ html = getHTML(conn);
+ assertEquals(MessageFormat.format(loginPageTemplate,
+ "<font color=\"red\">Error: Invalid Username or Password</font><br>", "", "http://foo:11000/oozie"), html);
+ }
+
+ public void testPostInvalidUsernamePassword() throws Exception {
+ URL url = new URL(container.getServletURL("/") + "?backurl=http://foo:11000/oozie&username=foo&password=bar");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+ String html = getHTML(conn);
+ assertEquals(MessageFormat.format(loginPageTemplate,
+ "<font color=\"red\">Error: Invalid Username or Password</font><br>", "foo", "http://foo:11000/oozie"), html);
+ }
+
+ public void testPostSuccess() throws Exception {
+ // Now that its actually going to work successfully, the backurl needs to go somewhere real; about:blank provides a
+ // convinient location that doesn't require internet access or another servlet running locally
+ URL url = new URL(container.getServletURL("/") + "?backurl=about:blank&username=foo&password=foo");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ assertEquals(HttpServletResponse.SC_FOUND, conn.getResponseCode());
+ String cookies = getCookies(conn);
+ assertTrue(cookies.contains("oozie.web.login.auth=foo"));
+ }
+
+ protected String getHTML(HttpURLConnection conn) throws Exception {
+ BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ String line;
+ StringBuilder htmlBuilder = new StringBuilder();
+ while ((line = br.readLine()) != null) {
+ htmlBuilder.append(line);
+ htmlBuilder.append("\n");
+ }
+ br.close();
+ return htmlBuilder.toString();
+ }
+
+ protected String getCookies(HttpURLConnection conn) throws Exception {
+ Map<String, List<String>> headers = conn.getHeaderFields();
+ for (String key : headers.keySet()) {
+ if (key != null && key.equals("Set-Cookie")) {
+ List<String> cookies = headers.get(key);
+ return cookies.get(0);
+ }
+ }
+ return null;
+ }
+}
Modified: oozie/trunk/pom.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/pom.xml?rev=1415882&r1=1415881&r2=1415882&view=diff
==============================================================================
--- oozie/trunk/pom.xml (original)
+++ oozie/trunk/pom.xml Fri Nov 30 23:09:35 2012
@@ -924,5 +924,14 @@
<hadoop.auth.version>3.0.0-SNAPSHOT</hadoop.auth.version>
</properties>
</profile>
+ <profile>
+ <id>loginServerExample</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <modules>
+ <module>login</module>
+ </modules>
+ </profile>
</profiles>
</project>
Modified: oozie/trunk/release-log.txt
URL: http://svn.apache.org/viewvc/oozie/trunk/release-log.txt?rev=1415882&r1=1415881&r2=1415882&view=diff
==============================================================================
--- oozie/trunk/release-log.txt (original)
+++ oozie/trunk/release-log.txt Fri Nov 30 23:09:35 2012
@@ -1,5 +1,6 @@
-- Oozie 3.4.0 release (trunk - unreleased)
+OOZIE-1103 Create example using AltKerberosAuthenticationHandler (rkanter)
OOZIE-1106 latest and future function do not work correctly when oozie processing timezone is non UTC (rohini via tucu)
OOZIE-1102 Update Oozie README.txt to have the TLP mailing list and links (jaoki via rkanter)
OOZIE-1096 Update wfgen README.txt to have the TLP mailing list (jun aoki via rkanter)
Modified: oozie/trunk/src/main/assemblies/distro.xml
URL: http://svn.apache.org/viewvc/oozie/trunk/src/main/assemblies/distro.xml?rev=1415882&r1=1415881&r2=1415882&view=diff
==============================================================================
--- oozie/trunk/src/main/assemblies/distro.xml (original)
+++ oozie/trunk/src/main/assemblies/distro.xml Fri Nov 30 23:09:35 2012
@@ -107,6 +107,16 @@
</includes>
<fileMode>0555</fileMode>
</fileSet>
+ <!-- Oozie Login Server Example war and jar -->
+ <fileSet>
+ <directory>${basedir}/../login/target</directory>
+ <outputDirectory>/</outputDirectory>
+ <includes>
+ <include>oozie-login.war</include>
+ <include>oozie-login.jar</include>
+ </includes>
+ <fileMode>0555</fileMode>
+ </fileSet>
</fileSets>
<files>