hadoop-common-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a..@apache.org
Subject svn commit: r1159804 [1/3] - in /hadoop/common/trunk: ./ hadoop-alfredo/ hadoop-alfredo/src/ hadoop-alfredo/src/examples/ hadoop-alfredo/src/examples/src/ hadoop-alfredo/src/examples/src/main/ hadoop-alfredo/src/examples/src/main/java/ hadoop-alfredo/s...
Date Fri, 19 Aug 2011 22:31:09 GMT
Author: atm
Date: Fri Aug 19 22:31:06 2011
New Revision: 1159804

URL: http://svn.apache.org/viewvc?rev=1159804&view=rev
Log:
HADOOP-7119. add Kerberos HTTP SPNEGO authentication support to Hadoop JT/NN/DN/TT web-consoles. (Alejandro Abdelnur via atm)

Added:
    hadoop/common/trunk/hadoop-alfredo/
    hadoop/common/trunk/hadoop-alfredo/BUILDING.txt
    hadoop/common/trunk/hadoop-alfredo/README.txt
    hadoop/common/trunk/hadoop-alfredo/pom.xml
    hadoop/common/trunk/hadoop-alfredo/src/
    hadoop/common/trunk/hadoop-alfredo/src/examples/
    hadoop/common/trunk/hadoop-alfredo/src/examples/pom.xml
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/RequestLoggerFilter.java
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoClient.java
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoServlet.java
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/resources/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/resources/log4j.properties
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/WEB-INF/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/WEB-INF/web.xml
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/annonymous/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/annonymous/index.html
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/index.html
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/kerberos/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/kerberos/index.html
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/simple/
    hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/simple/index.html
    hadoop/common/trunk/hadoop-alfredo/src/main/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticatedURL.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticationException.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/Authenticator.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/KerberosAuthenticator.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/PseudoAuthenticator.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/AuthenticationFilter.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/AuthenticationHandler.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/AuthenticationToken.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/KerberosAuthenticationHandler.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/PseudoAuthenticationHandler.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/util/
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/util/KerberosName.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/util/Signer.java
    hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/util/SignerException.java
    hadoop/common/trunk/hadoop-alfredo/src/site/
    hadoop/common/trunk/hadoop-alfredo/src/site/apt/
    hadoop/common/trunk/hadoop-alfredo/src/site/apt/BuildingIt.apt.vm
    hadoop/common/trunk/hadoop-alfredo/src/site/apt/Configuration.apt.vm
    hadoop/common/trunk/hadoop-alfredo/src/site/apt/Examples.apt.vm
    hadoop/common/trunk/hadoop-alfredo/src/site/apt/index.apt.vm
    hadoop/common/trunk/hadoop-alfredo/src/site/site.xml
    hadoop/common/trunk/hadoop-alfredo/src/test/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/KerberosTestUtils.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/client/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/client/AuthenticatorTestCase.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/client/TestAuthenticatedURL.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/client/TestKerberosAuthenticator.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/client/TestPseudoAuthenticator.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/server/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/server/TestAuthenticationFilter.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/server/TestAuthenticationToken.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/server/TestKerberosAuthenticationHandler.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/server/TestPseudoAuthenticationHandler.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/util/
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/util/TestKerberosName.java
    hadoop/common/trunk/hadoop-alfredo/src/test/java/org/apache/hadoop/alfredo/util/TestSigner.java
    hadoop/common/trunk/hadoop-alfredo/src/test/resources/
    hadoop/common/trunk/hadoop-alfredo/src/test/resources/krb5.conf
    hadoop/common/trunk/hadoop-common/src/main/docs/src/documentation/content/xdocs/HttpAuthentication.xml
    hadoop/common/trunk/hadoop-common/src/main/java/org/apache/hadoop/security/AuthenticationFilterInitializer.java
    hadoop/common/trunk/hadoop-common/src/main/java/org/apache/hadoop/security/HadoopKerberosName.java
    hadoop/common/trunk/hadoop-common/src/test/java/org/apache/hadoop/security/TestAuthenticationFilter.java
Modified:
    hadoop/common/trunk/hadoop-common/CHANGES.txt
    hadoop/common/trunk/hadoop-common/pom.xml
    hadoop/common/trunk/hadoop-common/src/main/docs/src/documentation/content/xdocs/site.xml
    hadoop/common/trunk/hadoop-common/src/main/java/org/apache/hadoop/security/SecurityUtil.java
    hadoop/common/trunk/hadoop-common/src/main/java/org/apache/hadoop/security/User.java
    hadoop/common/trunk/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java
    hadoop/common/trunk/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenIdentifier.java
    hadoop/common/trunk/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java
    hadoop/common/trunk/hadoop-common/src/main/resources/core-default.xml
    hadoop/common/trunk/hadoop-project/pom.xml
    hadoop/common/trunk/pom.xml

Added: hadoop/common/trunk/hadoop-alfredo/BUILDING.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/BUILDING.txt?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/BUILDING.txt (added)
+++ hadoop/common/trunk/hadoop-alfredo/BUILDING.txt Fri Aug 19 22:31:06 2011
@@ -0,0 +1,20 @@
+
+Build instructions for Hadoop Alfredo
+
+Same as for Hadoop.
+
+For more details refer to the Alfredo documentation pages.
+
+-----------------------------------------------------------------------------
+Caveats:
+
+* Alfredo has profile to enable Kerberos testcases (testKerberos)
+
+  To run Kerberos testcases a KDC, 2 kerberos principals and a keytab file
+  are required (refer to the Alfredo documentation pages for details).
+
+* Alfredo does not have a distribution profile (dist)
+
+* Alfredo does not have a native code profile (native)
+
+-----------------------------------------------------------------------------

Added: hadoop/common/trunk/hadoop-alfredo/README.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/README.txt?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/README.txt (added)
+++ hadoop/common/trunk/hadoop-alfredo/README.txt Fri Aug 19 22:31:06 2011
@@ -0,0 +1,15 @@
+Hadoop Alfredo, Java HTTP SPNEGO
+
+Hadoop Alfredo is a Java library consisting of a client and a server
+components to enable Kerberos SPNEGO authentication for HTTP.
+
+The client component is the AuthenticatedURL class.
+
+The server component is the AuthenticationFilter servlet filter class.
+
+Authentication mechanisms support is pluggable in both the client and
+the server components via interfaces.
+
+In addition to Kerberos SPNEGO, Alfredo also supports Pseudo/Simple
+authentication (trusting the value of the query string parameter
+'user.name').

Added: hadoop/common/trunk/hadoop-alfredo/pom.xml
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/pom.xml?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/pom.xml (added)
+++ hadoop/common/trunk/hadoop-alfredo/pom.xml Fri Aug 19 22:31:06 2011
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed 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. See accompanying LICENSE file.
+-->
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.hadoop</groupId>
+    <artifactId>hadoop-project</artifactId>
+    <version>0.23.0-SNAPSHOT</version>
+    <relativePath>../hadoop-project</relativePath>
+  </parent>
+  <groupId>org.apache.hadoop</groupId>
+  <artifactId>hadoop-alfredo</artifactId>
+  <version>0.23.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>Apache Hadoop Alfredo</name>
+  <description>Apache Hadoop Alfredo - Java HTTP SPNEGO</description>
+  <url>http://hadoop.apache.org/alfredo</url>
+
+  <properties>
+    <maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format>
+    <kerberos.realm>LOCALHOST</kerberos.realm>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mortbay.jetty</groupId>
+      <artifactId>jetty</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <testResources>
+      <testResource>
+        <directory>${basedir}/src/test/resources</directory>
+        <filtering>true</filtering>
+        <includes>
+          <include>krb5.conf</include>
+        </includes>
+      </testResource>
+      <testResource>
+        <directory>${basedir}/src/test/resources</directory>
+        <filtering>false</filtering>
+        <excludes>
+          <exclude>krb5.conf</exclude>
+        </excludes>
+      </testResource>
+    </testResources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <forkMode>always</forkMode>
+          <forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds>
+          <systemPropertyVariables>
+            <java.security.krb5.conf>${project.build.directory}/test-classes/krb5.conf</java.security.krb5.conf>
+            <kerberos.realm>${kerberos.realm}</kerberos.realm>
+          </systemPropertyVariables>
+          <excludes>
+            <exclude>**/${test.exclude}.java</exclude>
+            <exclude>${test.exclude.pattern}</exclude>
+            <exclude>**/TestKerberosAuth*.java</exclude>
+            <exclude>**/Test*$*.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-source-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>prepare-package</phase>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <attach>true</attach>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>testKerberos</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <forkMode>always</forkMode>
+              <forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds>
+              <systemPropertyVariables>
+                <java.security.krb5.conf>${project.build.directory}/test-classes/krb5.conf</java.security.krb5.conf>
+                <kerberos.realm>${kerberos.realm}</kerberos.realm>
+              </systemPropertyVariables>
+              <excludes>
+                <exclude>**/${test.exclude}.java</exclude>
+                <exclude>${test.exclude.pattern}</exclude>
+                <exclude>**/Test*$*.java</exclude>
+              </excludes>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>docs</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-site-plugin</artifactId>
+            <executions>
+              <execution>
+                <phase>package</phase>
+                <goals>
+                  <goal>site</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-project-info-reports-plugin</artifactId>
+            <executions>
+              <execution>
+                <configuration>
+                  <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+                </configuration>
+                <phase>package</phase>
+                <goals>
+                  <goal>dependencies</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <executions>
+              <execution>
+                <phase>package</phase>
+                <goals>
+                  <goal>javadoc</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/pom.xml
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/pom.xml?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/pom.xml (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/pom.xml Fri Aug 19 22:31:06 2011
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed 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. See accompanying LICENSE file.
+-->
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.hadoop</groupId>
+    <artifactId>hadoop-project</artifactId>
+    <version>0.23.0-SNAPSHOT</version>
+    <relativePath>../hadoop-project</relativePath>
+  </parent>
+  <groupId>org.apache.hadoop</groupId>
+  <artifactId>hadoop-alfredo-examples</artifactId>
+  <version>0.23.0-SNAPSHOT</version>
+  <packaging>war</packaging>
+
+  <name>Hadoop Alfredo Examples</name>
+  <description>Hadoop Alfredo - Java HTTP SPNEGO Examples</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-alfredo</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>java</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <mainClass>org.apache.hadoop.alfredo.examples.WhoClient</mainClass>
+          <arguments>
+            <argument>${url}</argument>
+          </arguments>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/RequestLoggerFilter.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/RequestLoggerFilter.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/RequestLoggerFilter.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/RequestLoggerFilter.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,183 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.examples;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Servlet filter that logs HTTP request/response headers
+ */
+public class RequestLoggerFilter implements Filter {
+  private static Logger LOG = LoggerFactory.getLogger(RequestLoggerFilter.class);
+
+  @Override
+  public void init(FilterConfig filterConfig) throws ServletException {
+  }
+
+  @Override
+  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
+    throws IOException, ServletException {
+    if (!LOG.isDebugEnabled()) {
+      filterChain.doFilter(request, response);
+    }
+    else {
+      XHttpServletRequest xRequest = new XHttpServletRequest((HttpServletRequest) request);
+      XHttpServletResponse xResponse = new XHttpServletResponse((HttpServletResponse) response);
+      try {
+        LOG.debug(xRequest.getResquestInfo().toString());
+        filterChain.doFilter(xRequest, xResponse);
+      }
+      finally {
+        LOG.debug(xResponse.getResponseInfo().toString());
+      }
+    }
+  }
+
+  @Override
+  public void destroy() {
+  }
+
+  private static class XHttpServletRequest extends HttpServletRequestWrapper {
+
+    public XHttpServletRequest(HttpServletRequest request) {
+      super(request);
+    }
+
+    public StringBuffer getResquestInfo() {
+      StringBuffer sb = new StringBuffer(512);
+      sb.append("\n").append("> ").append(getMethod()).append(" ").append(getRequestURL());
+      if (getQueryString() != null) {
+        sb.append("?").append(getQueryString());
+      }
+      sb.append("\n");
+      Enumeration names = getHeaderNames();
+      while (names.hasMoreElements()) {
+        String name = (String) names.nextElement();
+        Enumeration values = getHeaders(name);
+        while (values.hasMoreElements()) {
+          String value = (String) values.nextElement();
+          sb.append("> ").append(name).append(": ").append(value).append("\n");
+        }
+      }
+      sb.append(">");
+      return sb;
+    }
+  }
+
+  private static class XHttpServletResponse extends HttpServletResponseWrapper {
+    private Map<String, List<String>> headers = new HashMap<String, List<String>>();
+    private int status;
+    private String message;
+
+    public XHttpServletResponse(HttpServletResponse response) {
+      super(response);
+    }
+
+    private List<String> getHeaderValues(String name, boolean reset) {
+      List<String> values = headers.get(name);
+      if (reset || values == null) {
+        values = new ArrayList<String>();
+        headers.put(name, values);
+      }
+      return values;
+    }
+
+    @Override
+    public void addCookie(Cookie cookie) {
+      super.addCookie(cookie);
+      List<String> cookies = getHeaderValues("Set-Cookie", false);
+      cookies.add(cookie.getName() + "=" + cookie.getValue());
+    }
+
+    @Override
+    public void sendError(int sc, String msg) throws IOException {
+      super.sendError(sc, msg);
+      status = sc;
+      message = msg;
+    }
+
+
+    @Override
+    public void sendError(int sc) throws IOException {
+      super.sendError(sc);
+      status = sc;
+    }
+
+    @Override
+    public void setStatus(int sc) {
+      super.setStatus(sc);
+      status = sc;
+    }
+
+    @Override
+    public void setStatus(int sc, String msg) {
+      super.setStatus(sc, msg);
+      status = sc;
+      message = msg;
+    }
+
+    @Override
+    public void setHeader(String name, String value) {
+      super.setHeader(name, value);
+      List<String> values = getHeaderValues(name, true);
+      values.add(value);
+    }
+
+    @Override
+    public void addHeader(String name, String value) {
+      super.addHeader(name, value);
+      List<String> values = getHeaderValues(name, false);
+      values.add(value);
+    }
+
+    public StringBuffer getResponseInfo() {
+      if (status == 0) {
+        status = 200;
+        message = "OK";
+      }
+      StringBuffer sb = new StringBuffer(512);
+      sb.append("\n").append("< ").append("status code: ").append(status);
+      if (message != null) {
+        sb.append(", message: ").append(message);
+      }
+      sb.append("\n");
+      for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
+        for (String value : entry.getValue()) {
+          sb.append("< ").append(entry.getKey()).append(": ").append(value).append("\n");
+        }
+      }
+      sb.append("<");
+      return sb;
+    }
+  }
+}

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoClient.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoClient.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoClient.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoClient.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,57 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.examples;
+
+import org.apache.hadoop.alfredo.client.AuthenticatedURL;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+/**
+ * Example that uses <code>AuthenticatedURL</code>.
+ */
+public class WhoClient {
+
+  public static void main(String[] args) {
+    try {
+      if (args.length != 1) {
+        System.err.println("Usage: <URL>");
+        System.exit(-1);
+      }
+      AuthenticatedURL.Token token = new AuthenticatedURL.Token();
+      URL url = new URL(args[0]);
+      HttpURLConnection conn = new AuthenticatedURL().openConnection(url, token);
+      System.out.println();
+      System.out.println("Token value: " + token);
+      System.out.println("Status code: " + conn.getResponseCode() + " " + conn.getResponseMessage());
+      System.out.println();
+      if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
+        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+        String line = reader.readLine();
+        while (line != null) {
+          System.out.println(line);
+          line = reader.readLine();
+        }
+        reader.close();
+      }
+      System.out.println();
+    }
+    catch (Exception ex) {
+      System.err.println("ERROR: " + ex.getMessage());
+      System.exit(-1);
+    }
+  }
+}

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoServlet.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoServlet.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoServlet.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/java/org/apache/hadoop/alfredo/examples/WhoServlet.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,43 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.examples;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.Writer;
+import java.text.MessageFormat;
+
+/**
+ * Example servlet that returns the user and principal of the request.
+ */
+public class WhoServlet extends HttpServlet {
+
+  @Override
+  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+    resp.setContentType("text/plain");
+    resp.setStatus(HttpServletResponse.SC_OK);
+    String user = req.getRemoteUser();
+    String principal = (req.getUserPrincipal() != null) ? req.getUserPrincipal().getName() : null;
+    Writer writer = resp.getWriter();
+    writer.write(MessageFormat.format("You are: user[{0}] principal[{1}]\n", user, principal));
+  }
+
+  @Override
+  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+    doGet(req, resp);
+  }
+}

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/resources/log4j.properties
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/resources/log4j.properties?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/resources/log4j.properties (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/resources/log4j.properties Fri Aug 19 22:31:06 2011
@@ -0,0 +1,19 @@
+#
+# Licensed 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. See accompanying LICENSE file.
+#
+log4j.appender.test=org.apache.log4j.ConsoleAppender
+log4j.appender.test.Target=System.out
+log4j.appender.test.layout=org.apache.log4j.PatternLayout
+log4j.appender.test.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+log4j.logger.org.apache.hadoop.alfredo=DEBUG, test

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/WEB-INF/web.xml?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/WEB-INF/web.xml (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/WEB-INF/web.xml Fri Aug 19 22:31:06 2011
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed 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. See accompanying LICENSE file.
+-->
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
+
+  <servlet>
+    <servlet-name>whoServlet</servlet-name>
+    <servlet-class>org.apache.hadoop.alfredo.examples.WhoServlet</servlet-class>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>whoServlet</servlet-name>
+    <url-pattern>/anonymous/who</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>whoServlet</servlet-name>
+    <url-pattern>/simple/who</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>whoServlet</servlet-name>
+    <url-pattern>/kerberos/who</url-pattern>
+  </servlet-mapping>
+
+  <filter>
+    <filter-name>requestLoggerFilter</filter-name>
+    <filter-class>org.apache.hadoop.alfredo.examples.RequestLoggerFilter</filter-class>
+  </filter>
+
+  <filter>
+    <filter-name>anonymousFilter</filter-name>
+    <filter-class>org.apache.hadoop.alfredo.server.AuthenticationFilter</filter-class>
+    <init-param>
+      <param-name>type</param-name>
+      <param-value>simple</param-value>
+    </init-param>
+    <init-param>
+      <param-name>simple.anonymous.allowed</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>token.validity</param-name>
+      <param-value>30</param-value>
+    </init-param>
+  </filter>
+
+  <filter>
+    <filter-name>simpleFilter</filter-name>
+    <filter-class>org.apache.hadoop.alfredo.server.AuthenticationFilter</filter-class>
+    <init-param>
+      <param-name>type</param-name>
+      <param-value>simple</param-value>
+    </init-param>
+    <init-param>
+      <param-name>simple.anonymous.allowed</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>token.validity</param-name>
+      <param-value>30</param-value>
+    </init-param>
+  </filter>
+
+  <filter>
+    <filter-name>kerberosFilter</filter-name>
+    <filter-class>org.apache.hadoop.alfredo.server.AuthenticationFilter</filter-class>
+    <init-param>
+      <param-name>type</param-name>
+      <param-value>kerberos</param-value>
+    </init-param>
+    <init-param>
+      <param-name>kerberos.principal</param-name>
+      <param-value>HTTP/localhost@LOCALHOST</param-value>
+    </init-param>
+    <init-param>
+      <param-name>kerberos.keytab</param-name>
+      <param-value>/tmp/alfredo.keytab</param-value>
+    </init-param>
+    <init-param>
+      <param-name>token.validity</param-name>
+      <param-value>30</param-value>
+    </init-param>
+  </filter>
+
+  <filter-mapping>
+    <filter-name>requestLoggerFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+  <filter-mapping>
+    <filter-name>anonymousFilter</filter-name>
+    <url-pattern>/anonymous/*</url-pattern>
+  </filter-mapping>
+
+  <filter-mapping>
+    <filter-name>simpleFilter</filter-name>
+    <url-pattern>/simple/*</url-pattern>
+  </filter-mapping>
+
+  <filter-mapping>
+    <filter-name>kerberosFilter</filter-name>
+    <url-pattern>/kerberos/*</url-pattern>
+  </filter-mapping>
+
+</web-app>

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/annonymous/index.html
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/annonymous/index.html?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/annonymous/index.html (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/annonymous/index.html Fri Aug 19 22:31:06 2011
@@ -0,0 +1,18 @@
+<!--
+ Licensed 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. See accompanying LICENSE file.
+-->
+<html>
+<body>
+<h1>Hello Hadoop Alfredo Pseudo/Simple Authentication with anonymous users!</h1>
+</body>
+</html>

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/index.html
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/index.html?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/index.html (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/index.html Fri Aug 19 22:31:06 2011
@@ -0,0 +1,18 @@
+<!--
+ Licensed 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. See accompanying LICENSE file.
+-->
+<html>
+<body>
+<h1>Hello Hadoop Alfredo Examples</h1>
+</body>
+</html>

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/kerberos/index.html
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/kerberos/index.html?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/kerberos/index.html (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/kerberos/index.html Fri Aug 19 22:31:06 2011
@@ -0,0 +1,18 @@
+<!--
+ Licensed 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. See accompanying LICENSE file.
+-->
+<html>
+<body>
+<h1>Hello Hadoop Alfredo Kerberos SPNEGO Authentication!</h1>
+</body>
+</html>

Added: hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/simple/index.html
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/simple/index.html?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/simple/index.html (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/examples/src/main/webapp/simple/index.html Fri Aug 19 22:31:06 2011
@@ -0,0 +1,18 @@
+<!--
+ Licensed 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. See accompanying LICENSE file.
+-->
+<html>
+<body>
+<h1>Hello Hadoop Alfredo Pseudo/Simple Authentication!</h1>
+</body>
+</html>

Added: hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticatedURL.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticatedURL.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticatedURL.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticatedURL.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,274 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.client;
+
+import org.apache.hadoop.alfredo.server.AuthenticationFilter;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The {@link AuthenticatedURL} class enables the use of the JDK {@link URL} class
+ * against HTTP endpoints protected with the {@link AuthenticationFilter}.
+ * <p/>
+ * The authentication mechanisms supported by default are Hadoop Simple  authentication
+ * (also known as pseudo authentication) and Kerberos SPNEGO authentication.
+ * <p/>
+ * Additional authentication mechanisms can be supported via {@link Authenticator} implementations.
+ * <p/>
+ * The default {@link Authenticator} is the {@link KerberosAuthenticator} class which supports
+ * automatic fallback from Kerberos SPNEGO to Hadoop Simple authentication.
+ * <p/>
+ * <code>AuthenticatedURL</code> instances are not thread-safe.
+ * <p/>
+ * The usage pattern of the {@link AuthenticatedURL} is:
+ * <p/>
+ * <pre>
+ *
+ * // establishing an initial connection
+ *
+ * URL url = new URL("http://foo:8080/bar");
+ * AuthenticatedURL.Token token = new AuthenticatedURL.Token();
+ * AuthenticatedURL aUrl = new AuthenticatedURL();
+ * HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection();
+ * ....
+ * // use the 'conn' instance
+ * ....
+ *
+ * // establishing a follow up connection using a token from the previous connection
+ *
+ * HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection();
+ * ....
+ * // use the 'conn' instance
+ * ....
+ *
+ * </pre>
+ */
+public class AuthenticatedURL {
+
+  /**
+   * Name of the HTTP cookie used for the authentication token between the client and the server.
+   */
+  public static final String AUTH_COOKIE = "alfredo.auth";
+
+  private static final String AUTH_COOKIE_EQ = AUTH_COOKIE + "=";
+
+  /**
+   * Client side authentication token.
+   */
+  public static class Token {
+
+    private String token;
+
+    /**
+     * Creates a token.
+     */
+    public Token() {
+    }
+
+    /**
+     * Creates a token using an existing string representation of the token.
+     *
+     * @param tokenStr string representation of the tokenStr.
+     */
+    public Token(String tokenStr) {
+      if (tokenStr == null) {
+        throw new IllegalArgumentException("tokenStr cannot be null");
+      }
+      set(tokenStr);
+    }
+
+    /**
+     * Returns if a token from the server has been set.
+     *
+     * @return if a token from the server has been set.
+     */
+    public boolean isSet() {
+      return token != null;
+    }
+
+    /**
+     * Sets a token.
+     *
+     * @param tokenStr string representation of the tokenStr.
+     */
+    void set(String tokenStr) {
+      token = tokenStr;
+    }
+
+    /**
+     * Returns the string representation of the token.
+     *
+     * @return the string representation of the token.
+     */
+    @Override
+    public String toString() {
+      return token;
+    }
+
+    /**
+     * Return the hashcode for the token.
+     *
+     * @return the hashcode for the token.
+     */
+    @Override
+    public int hashCode() {
+      return (token != null) ? token.hashCode() : 0;
+    }
+
+    /**
+     * Return if two token instances are equal.
+     *
+     * @param o the other token instance.
+     *
+     * @return if this instance and the other instance are equal.
+     */
+    @Override
+    public boolean equals(Object o) {
+      boolean eq = false;
+      if (o instanceof Token) {
+        Token other = (Token) o;
+        eq = (token == null && other.token == null) || (token != null && this.token.equals(other.token));
+      }
+      return eq;
+    }
+  }
+
+  private static Class<? extends Authenticator> DEFAULT_AUTHENTICATOR = KerberosAuthenticator.class;
+
+  /**
+   * Sets the default {@link Authenticator} class to use when an {@link AuthenticatedURL} instance
+   * is created without specifying an authenticator.
+   *
+   * @param authenticator the authenticator class to use as default.
+   */
+  public static void setDefaultAuthenticator(Class<? extends Authenticator> authenticator) {
+    DEFAULT_AUTHENTICATOR = authenticator;
+  }
+
+  /**
+   * Returns the default {@link Authenticator} class to use when an {@link AuthenticatedURL} instance
+   * is created without specifying an authenticator.
+   *
+   * @return the authenticator class to use as default.
+   */
+  public static Class<? extends Authenticator> getDefaultAuthenticator() {
+    return DEFAULT_AUTHENTICATOR;
+  }
+
+  private Authenticator authenticator;
+
+  /**
+   * Creates an {@link AuthenticatedURL}.
+   */
+  public AuthenticatedURL() {
+    this(null);
+  }
+
+  /**
+   * Creates an <code>AuthenticatedURL</code>.
+   *
+   * @param authenticator the {@link Authenticator} instance to use, if <code>null</code> a {@link
+   * KerberosAuthenticator} is used.
+   */
+  public AuthenticatedURL(Authenticator authenticator) {
+    try {
+      this.authenticator = (authenticator != null) ? authenticator : DEFAULT_AUTHENTICATOR.newInstance();
+    } catch (Exception ex) {
+      throw new RuntimeException(ex);
+    }
+  }
+
+  /**
+   * Returns an authenticated {@link HttpURLConnection}.
+   *
+   * @param url the URL to connect to. Only HTTP/S URLs are supported.
+   * @param token the authentication token being used for the user.
+   *
+   * @return an authenticated {@link HttpURLConnection}.
+   *
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication exception occurred.
+   */
+  public HttpURLConnection openConnection(URL url, Token token) throws IOException, AuthenticationException {
+    if (url == null) {
+      throw new IllegalArgumentException("url cannot be NULL");
+    }
+    if (!url.getProtocol().equalsIgnoreCase("http") && !url.getProtocol().equalsIgnoreCase("https")) {
+      throw new IllegalArgumentException("url must be for a HTTP or HTTPS resource");
+    }
+    if (token == null) {
+      throw new IllegalArgumentException("token cannot be NULL");
+    }
+    authenticator.authenticate(url, token);
+    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+    injectToken(conn, token);
+    return conn;
+  }
+
+  /**
+   * Helper method that injects an authentication token to send with a connection.
+   *
+   * @param conn connection to inject the authentication token into.
+   * @param token authentication token to inject.
+   */
+  public static void injectToken(HttpURLConnection conn, Token token) {
+    String t = token.token;
+    if (t != null) {
+      if (!t.startsWith("\"")) {
+        t = "\"" + t + "\"";
+      }
+      conn.addRequestProperty("Cookie", AUTH_COOKIE_EQ + t);
+    }
+  }
+
+  /**
+   * Helper method that extracts an authentication token received from a connection.
+   * <p/>
+   * This method is used by {@link Authenticator} implementations.
+   *
+   * @param conn connection to extract the authentication token from.
+   * @param token the authentication token.
+   *
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication exception occurred.
+   */
+  public static void extractToken(HttpURLConnection conn, Token token) throws IOException, AuthenticationException {
+    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
+      Map<String, List<String>> headers = conn.getHeaderFields();
+      List<String> cookies = headers.get("Set-Cookie");
+      if (cookies != null) {
+        for (String cookie : cookies) {
+          if (cookie.startsWith(AUTH_COOKIE_EQ)) {
+            String value = cookie.substring(AUTH_COOKIE_EQ.length());
+            int separator = value.indexOf(";");
+            if (separator > -1) {
+              value = value.substring(0, separator);
+            }
+            if (value.length() > 0) {
+              token.set(value);
+            }
+          }
+        }
+      }
+    } else {
+      throw new AuthenticationException("Authentication failed, status: " + conn.getResponseCode() +
+                                        ", message: " + conn.getResponseMessage());
+    }
+  }
+
+}

Added: hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticationException.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticationException.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticationException.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/AuthenticationException.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,50 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.client;
+
+/**
+ * Exception thrown when an authentication error occurrs.
+ */
+public class AuthenticationException extends Exception {
+  
+  static final long serialVersionUID = 0;
+
+  /**
+   * Creates an {@link AuthenticationException}.
+   *
+   * @param cause original exception.
+   */
+  public AuthenticationException(Throwable cause) {
+    super(cause);
+  }
+
+  /**
+   * Creates an {@link AuthenticationException}.
+   *
+   * @param msg exception message.
+   */
+  public AuthenticationException(String msg) {
+    super(msg);
+  }
+
+  /**
+   * Creates an {@link AuthenticationException}.
+   *
+   * @param msg exception message.
+   * @param cause original exception.
+   */
+  public AuthenticationException(String msg, Throwable cause) {
+    super(msg, cause);
+  }
+}

Added: hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/Authenticator.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/Authenticator.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/Authenticator.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/Authenticator.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,39 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.client;
+
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * Interface for client authentication mechanisms.
+ * <p/>
+ * Implementations are use-once instances, they don't need to be thread safe.
+ */
+public interface Authenticator {
+
+  /**
+   * Authenticates against a URL and returns a {@link AuthenticatedURL.Token} to be
+   * used by subsequent requests.
+   *
+   * @param url the URl to authenticate against.
+   * @param token the authentication token being used for the user.
+   *
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication error occurred.
+   */
+  public void authenticate(URL url, AuthenticatedURL.Token token) throws IOException, AuthenticationException;
+
+}

Added: hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/KerberosAuthenticator.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/KerberosAuthenticator.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/KerberosAuthenticator.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/KerberosAuthenticator.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,270 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.client;
+
+import com.sun.security.auth.module.Krb5LoginModule;
+import org.apache.commons.codec.binary.Base64;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import sun.security.jgss.GSSUtil;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The {@link KerberosAuthenticator} implements the Kerberos SPNEGO authentication sequence.
+ * <p/>
+ * It uses the default principal for the Kerberos cache (normally set via kinit).
+ * <p/>
+ * It falls back to the {@link PseudoAuthenticator} if the HTTP endpoint does not trigger an SPNEGO authentication
+ * sequence.
+ */
+public class KerberosAuthenticator implements Authenticator {
+
+  /**
+   * HTTP header used by the SPNEGO server endpoint during an authentication sequence.
+   */
+  public static String WWW_AUTHENTICATE = "WWW-Authenticate";
+
+  /**
+   * HTTP header used by the SPNEGO client endpoint during an authentication sequence.
+   */
+  public static String AUTHORIZATION = "Authorization";
+
+  /**
+   * HTTP header prefix used by the SPNEGO client/server endpoints during an authentication sequence.
+   */
+  public static String NEGOTIATE = "Negotiate";
+
+  private static final String AUTH_HTTP_METHOD = "OPTIONS";
+
+  /*
+  * Defines the Kerberos configuration that will be used to obtain the Kerberos principal from the
+  * Kerberos cache.
+  */
+  private static class KerberosConfiguration extends Configuration {
+
+    private static final String OS_LOGIN_MODULE_NAME;
+    private static final boolean windows = System.getProperty("os.name").startsWith("Windows");
+
+    static {
+      if (windows) {
+        OS_LOGIN_MODULE_NAME = "com.sun.security.auth.module.NTLoginModule";
+      } else {
+        OS_LOGIN_MODULE_NAME = "com.sun.security.auth.module.UnixLoginModule";
+      }
+    }
+
+    private static final AppConfigurationEntry OS_SPECIFIC_LOGIN =
+      new AppConfigurationEntry(OS_LOGIN_MODULE_NAME,
+                                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+                                new HashMap<String, String>());
+
+    private static final Map<String, String> USER_KERBEROS_OPTIONS = new HashMap<String, String>();
+
+    static {
+      USER_KERBEROS_OPTIONS.put("doNotPrompt", "true");
+      USER_KERBEROS_OPTIONS.put("useTicketCache", "true");
+      USER_KERBEROS_OPTIONS.put("renewTGT", "true");
+      String ticketCache = System.getenv("KRB5CCNAME");
+      if (ticketCache != null) {
+        USER_KERBEROS_OPTIONS.put("ticketCache", ticketCache);
+      }
+    }
+
+    private static final AppConfigurationEntry USER_KERBEROS_LOGIN =
+      new AppConfigurationEntry(Krb5LoginModule.class.getName(),
+                                AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL,
+                                USER_KERBEROS_OPTIONS);
+
+    private static final AppConfigurationEntry[] USER_KERBEROS_CONF =
+      new AppConfigurationEntry[]{OS_SPECIFIC_LOGIN, USER_KERBEROS_LOGIN};
+
+    @Override
+    public AppConfigurationEntry[] getAppConfigurationEntry(String appName) {
+      return USER_KERBEROS_CONF;
+    }
+  }
+
+  static {
+    javax.security.auth.login.Configuration.setConfiguration(new KerberosConfiguration());
+  }
+
+  private URL url;
+  private HttpURLConnection conn;
+  private Base64 base64;
+
+  /**
+   * Performs SPNEGO authentication against the specified URL.
+   * <p/>
+   * If a token is given it does a NOP and returns the given token.
+   * <p/>
+   * If no token is given, it will perform the SPNEGO authentication sequence using an
+   * HTTP <code>OPTIONS</code> request.
+   *
+   * @param url the URl to authenticate against.
+   * @param token the authentication token being used for the user.
+   *
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication error occurred.
+   */
+  @Override
+  public void authenticate(URL url, AuthenticatedURL.Token token)
+    throws IOException, AuthenticationException {
+    if (!token.isSet()) {
+      this.url = url;
+      base64 = new Base64(0);
+      conn = (HttpURLConnection) url.openConnection();
+      conn.setRequestMethod(AUTH_HTTP_METHOD);
+      conn.connect();
+      if (isNegotiate()) {
+        doSpnegoSequence(token);
+      } else {
+        getFallBackAuthenticator().authenticate(url, token);
+      }
+    }
+  }
+
+  /**
+   * If the specified URL does not support SPNEGO authentication, a fallback {@link Authenticator} will be used.
+   * <p/>
+   * This implementation returns a {@link PseudoAuthenticator}.
+   *
+   * @return the fallback {@link Authenticator}.
+   */
+  protected Authenticator getFallBackAuthenticator() {
+    return new PseudoAuthenticator();
+  }
+
+  /*
+  * Indicates if the response is starting a SPNEGO negotiation.
+  */
+  private boolean isNegotiate() throws IOException {
+    boolean negotiate = false;
+    if (conn.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
+      String authHeader = conn.getHeaderField(WWW_AUTHENTICATE);
+      negotiate = authHeader != null && authHeader.trim().startsWith(NEGOTIATE);
+    }
+    return negotiate;
+  }
+
+  /**
+   * Implements the SPNEGO authentication sequence interaction using the current default principal
+   * in the Kerberos cache (normally set via kinit).
+   *
+   * @param token the authentication token being used for the user.
+   *
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication error occurred.
+   */
+  private void doSpnegoSequence(AuthenticatedURL.Token token) throws IOException, AuthenticationException {
+    try {
+      AccessControlContext context = AccessController.getContext();
+      Subject subject = Subject.getSubject(context);
+      if (subject == null) {
+        subject = new Subject();
+        LoginContext login = new LoginContext("", subject);
+        login.login();
+      }
+      Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
+
+        @Override
+        public Void run() throws Exception {
+          GSSContext gssContext = null;
+          try {
+            GSSManager gssManager = GSSManager.getInstance();
+            String servicePrincipal = "HTTP/" + KerberosAuthenticator.this.url.getHost();
+            GSSName serviceName = gssManager.createName(servicePrincipal,
+                                                        GSSUtil.NT_GSS_KRB5_PRINCIPAL);
+            gssContext = gssManager.createContext(serviceName, GSSUtil.GSS_KRB5_MECH_OID, null,
+                                                  GSSContext.DEFAULT_LIFETIME);
+            gssContext.requestCredDeleg(true);
+            gssContext.requestMutualAuth(true);
+
+            byte[] inToken = new byte[0];
+            byte[] outToken;
+            boolean established = false;
+
+            // Loop while the context is still not established
+            while (!established) {
+              outToken = gssContext.initSecContext(inToken, 0, inToken.length);
+              if (outToken != null) {
+                sendToken(outToken);
+              }
+
+              if (!gssContext.isEstablished()) {
+                inToken = readToken();
+              } else {
+                established = true;
+              }
+            }
+          } finally {
+            if (gssContext != null) {
+              gssContext.dispose();
+              gssContext = null;
+            }
+          }
+          return null;
+        }
+      });
+    } catch (PrivilegedActionException ex) {
+      throw new AuthenticationException(ex.getException());
+    } catch (LoginException ex) {
+      throw new AuthenticationException(ex);
+    }
+    AuthenticatedURL.extractToken(conn, token);
+  }
+
+  /*
+  * Sends the Kerberos token to the server.
+  */
+  private void sendToken(byte[] outToken) throws IOException, AuthenticationException {
+    String token = base64.encodeToString(outToken);
+    conn = (HttpURLConnection) url.openConnection();
+    conn.setRequestMethod(AUTH_HTTP_METHOD);
+    conn.setRequestProperty(AUTHORIZATION, NEGOTIATE + " " + token);
+    conn.connect();
+  }
+
+  /*
+  * Retrieves the Kerberos token returned by the server.
+  */
+  private byte[] readToken() throws IOException, AuthenticationException {
+    int status = conn.getResponseCode();
+    if (status == HttpURLConnection.HTTP_OK || status == HttpURLConnection.HTTP_UNAUTHORIZED) {
+      String authHeader = conn.getHeaderField(WWW_AUTHENTICATE);
+      if (authHeader == null || !authHeader.trim().startsWith(NEGOTIATE)) {
+        throw new AuthenticationException("Invalid SPNEGO sequence, '" + WWW_AUTHENTICATE +
+                                          "' header incorrect: " + authHeader);
+      }
+      String negotiation = authHeader.trim().substring((NEGOTIATE + " ").length()).trim();
+      return base64.decode(negotiation);
+    }
+    throw new AuthenticationException("Invalid SPNEGO sequence, status code: " + status);
+  }
+
+}

Added: hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/PseudoAuthenticator.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/PseudoAuthenticator.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/PseudoAuthenticator.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/client/PseudoAuthenticator.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,74 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.client;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+/**
+ * The {@link PseudoAuthenticator} implementation provides an authentication equivalent to Hadoop's
+ * Simple authentication, it trusts the value of the 'user.name' Java System property.
+ * <p/>
+ * The 'user.name' value is propagated using an additional query string parameter {@link #USER_NAME} ('user.name').
+ */
+public class PseudoAuthenticator implements Authenticator {
+
+  /**
+   * Name of the additional parameter that carries the 'user.name' value.
+   */
+  public static final String USER_NAME = "user.name";
+
+  private static final String USER_NAME_EQ = USER_NAME + "=";
+
+  /**
+   * Performs simple authentication against the specified URL.
+   * <p/>
+   * If a token is given it does a NOP and returns the given token.
+   * <p/>
+   * If no token is given, it will perform an HTTP <code>OPTIONS</code> request injecting an additional
+   * parameter {@link #USER_NAME} in the query string with the value returned by the {@link #getUserName()}
+   * method.
+   * <p/>
+   * If the response is successful it will update the authentication token.
+   *
+   * @param url the URl to authenticate against.
+   * @param token the authencation token being used for the user.
+   *
+   * @throws IOException if an IO error occurred.
+   * @throws AuthenticationException if an authentication error occurred.
+   */
+  @Override
+  public void authenticate(URL url, AuthenticatedURL.Token token) throws IOException, AuthenticationException {
+    String strUrl = url.toString();
+    String paramSeparator = (strUrl.contains("?")) ? "&" : "?";
+    strUrl += paramSeparator + USER_NAME_EQ + getUserName();
+    url = new URL(strUrl);
+    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+    conn.setRequestMethod("OPTIONS");
+    conn.connect();
+    AuthenticatedURL.extractToken(conn, token);
+  }
+
+  /**
+   * Returns the current user name.
+   * <p/>
+   * This implementation returns the value of the Java system property 'user.name'
+   *
+   * @return the current user name.
+   */
+  protected String getUserName() {
+    return System.getProperty("user.name");
+  }
+}

Added: hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/AuthenticationFilter.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/AuthenticationFilter.java?rev=1159804&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/AuthenticationFilter.java (added)
+++ hadoop/common/trunk/hadoop-alfredo/src/main/java/org/apache/hadoop/alfredo/server/AuthenticationFilter.java Fri Aug 19 22:31:06 2011
@@ -0,0 +1,402 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.apache.hadoop.alfredo.server;
+
+import org.apache.hadoop.alfredo.client.AuthenticatedURL;
+import org.apache.hadoop.alfredo.client.AuthenticationException;
+import org.apache.hadoop.alfredo.util.Signer;
+import org.apache.hadoop.alfredo.util.SignerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.Random;
+
+/**
+ * The {@link AuthenticationFilter} enables protecting web application resources with different (pluggable)
+ * authentication mechanisms.
+ * <p/>
+ * Out of the box it provides 2 authentication mechanisms: Pseudo and Kerberos SPNEGO.
+ * <p/>
+ * Additional authentication mechanisms are supported via the {@link AuthenticationHandler} interface.
+ * <p/>
+ * This filter delegates to the configured authentication handler for authentication and once it obtains an
+ * {@link AuthenticationToken} from it, sets a signed HTTP cookie with the token. For client requests
+ * that provide the signed HTTP cookie, it verifies the validity of the cookie, extracts the user information
+ * and lets the request proceed to the target resource.
+ * <p/>
+ * The supported configuration properties are:
+ * <ul>
+ * <li>config.prefix: indicates the prefix to be used by all other configuration properties, the default value
+ * is no prefix. See below for details on how/why this prefix is used.</li>
+ * <li>[#PREFIX#.]type: simple|kerberos|#CLASS#, 'simple' is short for the
+ * {@link PseudoAuthenticationHandler}, 'kerberos' is short for {@link KerberosAuthenticationHandler}, otherwise
+ * the full class name of the {@link AuthenticationHandler} must be specified.</li>
+ * <li>[#PREFIX#.]signature.secret: the secret used to sign the HTTP cookie value. The default value is a random
+ * value. Unless multiple webapp instances need to share the secret the random value is adequate.</li>
+ * <li>[#PREFIX#.]token.validity: time -in seconds- that the generated token is valid before a
+ * new authentication is triggered, default value is <code>3600</code> seconds.</li>
+ * <li>[#PREFIX#.]cookie.domain: domain to use for the HTTP cookie that stores the authentication token.</li>
+ * <li>[#PREFIX#.]cookie.path: path to use for the HTTP cookie that stores the authentication token.</li>
+ * </ul>
+ * <p/>
+ * The rest of the configuration properties are specific to the {@link AuthenticationHandler} implementation and the
+ * {@link AuthenticationFilter} will take all the properties that start with the prefix #PREFIX#, it will remove
+ * the prefix from it and it will pass them to the the authentication handler for initialization. Properties that do
+ * not start with the prefix will not be passed to the authentication handler initialization.
+ */
+public class AuthenticationFilter implements Filter {
+
+  private static Logger LOG = LoggerFactory.getLogger(AuthenticationFilter.class);
+
+  /**
+   * Constant for the property that specifies the configuration prefix.
+   */
+  public static final String CONFIG_PREFIX = "config.prefix";
+
+  /**
+   * Constant for the property that specifies the authentication handler to use.
+   */
+  public static final String AUTH_TYPE = "type";
+
+  /**
+   * Constant for the property that specifies the secret to use for signing the HTTP Cookies.
+   */
+  public static final String SIGNATURE_SECRET = "signature.secret";
+
+  /**
+   * Constant for the configuration property that indicates the validity of the generated token.
+   */
+  public static final String AUTH_TOKEN_VALIDITY = "token.validity";
+
+  /**
+   * Constant for the configuration property that indicates the domain to use in the HTTP cookie.
+   */
+  public static final String COOKIE_DOMAIN = "cookie.domain";
+
+  /**
+   * Constant for the configuration property that indicates the path to use in the HTTP cookie.
+   */
+  public static final String COOKIE_PATH = "cookie.path";
+
+  private Signer signer;
+  private AuthenticationHandler authHandler;
+  private boolean randomSecret;
+  private long validity;
+  private String cookieDomain;
+  private String cookiePath;
+
+  /**
+   * Initializes the authentication filter.
+   * <p/>
+   * It instantiates and initializes the specified {@link AuthenticationHandler}.
+   * <p/>
+   *
+   * @param filterConfig filter configuration.
+   *
+   * @throws ServletException thrown if the filter or the authentication handler could not be initialized properly.
+   */
+  @Override
+  public void init(FilterConfig filterConfig) throws ServletException {
+    String configPrefix = filterConfig.getInitParameter(CONFIG_PREFIX);
+    configPrefix = (configPrefix != null) ? configPrefix + "." : "";
+    Properties config = getConfiguration(configPrefix, filterConfig);
+    String authHandlerName = config.getProperty(AUTH_TYPE, null);
+    String authHandlerClassName;
+    if (authHandlerName == null) {
+      throw new ServletException("Authentication type must be specified: simple|kerberos|<class>");
+    }
+    if (authHandlerName.equals("simple")) {
+      authHandlerClassName = PseudoAuthenticationHandler.class.getName();
+    } else if (authHandlerName.equals("kerberos")) {
+      authHandlerClassName = KerberosAuthenticationHandler.class.getName();
+    } else {
+      authHandlerClassName = authHandlerName;
+    }
+
+    try {
+      Class klass = Thread.currentThread().getContextClassLoader().loadClass(authHandlerClassName);
+      authHandler = (AuthenticationHandler) klass.newInstance();
+      authHandler.init(config);
+    } catch (ClassNotFoundException ex) {
+      throw new ServletException(ex);
+    } catch (InstantiationException ex) {
+      throw new ServletException(ex);
+    } catch (IllegalAccessException ex) {
+      throw new ServletException(ex);
+    }
+    String signatureSecret = config.getProperty(configPrefix + SIGNATURE_SECRET);
+    if (signatureSecret == null) {
+      signatureSecret = Long.toString(new Random(System.currentTimeMillis()).nextLong());
+      randomSecret = true;
+      LOG.warn("'signature.secret' configuration not set, using a random value as secret");
+    }
+    signer = new Signer(signatureSecret.getBytes());
+    validity = Long.parseLong(config.getProperty(AUTH_TOKEN_VALIDITY, "36000")) * 1000; //10 hours
+
+    cookieDomain = config.getProperty(COOKIE_DOMAIN, null);
+    cookiePath = config.getProperty(COOKIE_PATH, null);
+  }
+
+  /**
+   * Returns the authentication handler being used.
+   *
+   * @return the authentication handler being used.
+   */
+  protected AuthenticationHandler getAuthenticationHandler() {
+    return authHandler;
+  }
+
+  /**
+   * Returns if a random secret is being used.
+   *
+   * @return if a random secret is being used.
+   */
+  protected boolean isRandomSecret() {
+    return randomSecret;
+  }
+
+  /**
+   * Returns the validity time of the generated tokens.
+   *
+   * @return the validity time of the generated tokens, in seconds.
+   */
+  protected long getValidity() {
+    return validity / 1000;
+  }
+
+  /**
+   * Returns the cookie domain to use for the HTTP cookie.
+   *
+   * @return the cookie domain to use for the HTTP cookie.
+   */
+  protected String getCookieDomain() {
+    return cookieDomain;
+  }
+
+  /**
+   * Returns the cookie path to use for the HTTP cookie.
+   *
+   * @return the cookie path to use for the HTTP cookie.
+   */
+  protected String getCookiePath() {
+    return cookiePath;
+  }
+
+  /**
+   * Destroys the filter.
+   * <p/>
+   * It invokes the {@link AuthenticationHandler#destroy()} method to release any resources it may hold.
+   */
+  @Override
+  public void destroy() {
+    if (authHandler != null) {
+      authHandler.destroy();
+      authHandler = null;
+    }
+  }
+
+  /**
+   * Returns the filtered configuration (only properties starting with the specified prefix). The property keys
+   * are also trimmed from the prefix. The returned {@link Properties} object is used to initialized the
+   * {@link AuthenticationHandler}.
+   * <p/>
+   * This method can be overriden by subclasses to obtain the configuration from other configuration source than
+   * the web.xml file.
+   *
+   * @param configPrefix configuration prefix to use for extracting configuration properties.
+   * @param filterConfig filter configuration object
+   *
+   * @return the configuration to be used with the {@link AuthenticationHandler} instance.
+   *
+   * @throws ServletException thrown if the configuration could not be created.
+   */
+  protected Properties getConfiguration(String configPrefix, FilterConfig filterConfig) throws ServletException {
+    Properties props = new Properties();
+    Enumeration names = filterConfig.getInitParameterNames();
+    while (names.hasMoreElements()) {
+      String name = (String) names.nextElement();
+      if (name.startsWith(configPrefix)) {
+        String value = filterConfig.getInitParameter(name);
+        props.put(name.substring(configPrefix.length()), value);
+      }
+    }
+    return props;
+  }
+
+  /**
+   * Returns the full URL of the request including the query string.
+   * <p/>
+   * Used as a convenience method for logging purposes.
+   *
+   * @param request the request object.
+   *
+   * @return the full URL of the request including the query string.
+   */
+  protected String getRequestURL(HttpServletRequest request) {
+    StringBuffer sb = request.getRequestURL();
+    if (request.getQueryString() != null) {
+      sb.append("?").append(request.getQueryString());
+    }
+    return sb.toString();
+  }
+
+  /**
+   * Returns the {@link AuthenticationToken} for the request.
+   * <p/>
+   * It looks at the received HTTP cookies and extracts the value of the {@link AuthenticatedURL#AUTH_COOKIE}
+   * if present. It verifies the signature and if correct it creates the {@link AuthenticationToken} and returns
+   * it.
+   * <p/>
+   * If this method returns <code>null</code> the filter will invoke the configured {@link AuthenticationHandler}
+   * to perform user authentication.
+   *
+   * @param request request object.
+   *
+   * @return the Authentication token if the request is authenticated, <code>null</code> otherwise.
+   *
+   * @throws IOException thrown if an IO error occurred.
+   * @throws AuthenticationException thrown if the token is invalid or if it has expired.
+   */
+  protected AuthenticationToken getToken(HttpServletRequest request) throws IOException, AuthenticationException {
+    AuthenticationToken token = null;
+    String tokenStr = null;
+    Cookie[] cookies = request.getCookies();
+    if (cookies != null) {
+      for (Cookie cookie : cookies) {
+        if (cookie.getName().equals(AuthenticatedURL.AUTH_COOKIE)) {
+          tokenStr = cookie.getValue();
+          try {
+            tokenStr = signer.verifyAndExtract(tokenStr);
+          } catch (SignerException ex) {
+            throw new AuthenticationException(ex);
+          }
+          break;
+        }
+      }
+    }
+    if (tokenStr != null) {
+      token = AuthenticationToken.parse(tokenStr);
+      if (!token.getType().equals(authHandler.getType())) {
+        throw new AuthenticationException("Invalid AuthenticationToken type");
+      }
+      if (token.isExpired()) {
+        throw new AuthenticationException("AuthenticationToken expired");
+      }
+    }
+    return token;
+  }
+
+  /**
+   * If the request has a valid authentication token it allows the request to continue to the target resource,
+   * otherwise it triggers an authentication sequence using the configured {@link AuthenticationHandler}.
+   *
+   * @param request the request object.
+   * @param response the response object.
+   * @param filterChain the filter chain object.
+   *
+   * @throws IOException thrown if an IO error occurred.
+   * @throws ServletException thrown if a processing error occurred.
+   */
+  @Override
+  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
+      throws IOException, ServletException {
+    HttpServletRequest httpRequest = (HttpServletRequest) request;
+    HttpServletResponse httpResponse = (HttpServletResponse) response;
+    try {
+      boolean newToken = false;
+      AuthenticationToken token = getToken(httpRequest);
+      if (token == null) {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Request [{}] triggering authentication", getRequestURL(httpRequest));
+        }
+        token = authHandler.authenticate(httpRequest, httpResponse);
+        if (token != null && token != AuthenticationToken.ANONYMOUS) {
+          token.setExpires(System.currentTimeMillis() + getValidity() * 1000);
+        }
+        newToken = true;
+      }
+      if (token != null) {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Request [{}] user [{}] authenticated", getRequestURL(httpRequest), token.getUserName());
+        }
+        final AuthenticationToken authToken = token;
+        httpRequest = new HttpServletRequestWrapper(httpRequest) {
+
+          @Override
+          public String getAuthType() {
+            return authToken.getType();
+          }
+
+          @Override
+          public String getRemoteUser() {
+            return authToken.getUserName();
+          }
+
+          @Override
+          public Principal getUserPrincipal() {
+            return (authToken != AuthenticationToken.ANONYMOUS) ? authToken : null;
+          }
+        };
+        if (newToken && token != AuthenticationToken.ANONYMOUS) {
+          String signedToken = signer.sign(token.toString());
+          Cookie cookie = createCookie(signedToken);
+          httpResponse.addCookie(cookie);
+        }
+        filterChain.doFilter(httpRequest, httpResponse);
+      }
+    } catch (AuthenticationException ex) {
+      if (!httpResponse.isCommitted()) {
+        Cookie cookie = createCookie("");
+        cookie.setMaxAge(0);
+        httpResponse.addCookie(cookie);
+        httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
+      }
+      LOG.warn("Authentication exception: " + ex.getMessage(), ex);
+    }
+  }
+
+  /**
+   * Creates the Alfredo authentiation HTTP cookie.
+   * <p/>
+   * It sets the domain and path specified in the configuration.
+   *
+   * @param token authentication token for the cookie.
+   *
+   * @return the HTTP cookie.
+   */
+  protected Cookie createCookie(String token) {
+    Cookie cookie = new Cookie(AuthenticatedURL.AUTH_COOKIE, token);
+    if (getCookieDomain() != null) {
+      cookie.setDomain(getCookieDomain());
+    }
+    if (getCookiePath() != null) {
+      cookie.setPath(getCookiePath());
+    }
+    return cookie;
+  }
+}



Mime
View raw message