Repository: knox Updated Branches: refs/heads/master 834d64325 -> 6212381ec
KNOX-1171: Handle invalid hadoop.auth cookie returned by Oozie Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/6212381e Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/6212381e Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/6212381e Branch: refs/heads/master Commit: 6212381ec38e1e7ad18a6ffb30656a8fe3c742fd Parents: 834d643 Author: Kevin Minder <[email protected]> Authored: Tue Feb 6 09:27:28 2018 -0500 Committer: Kevin Minder <[email protected]> Committed: Tue Feb 6 09:30:03 2018 -0500 ---------------------------------------------------------------------- .../apache/knox/gateway/SpiGatewayMessages.java | 5 + .../gateway/dispatch/HadoopAuthCookieStore.java | 115 ++++++++++++++++++- .../dispatch/HadoopAuthCookieStoreTest.java | 73 ++++++++++++ 3 files changed, 191 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/6212381e/gateway-spi/src/main/java/org/apache/knox/gateway/SpiGatewayMessages.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/SpiGatewayMessages.java b/gateway-spi/src/main/java/org/apache/knox/gateway/SpiGatewayMessages.java index ddcc073..8718b1d 100644 --- a/gateway-spi/src/main/java/org/apache/knox/gateway/SpiGatewayMessages.java +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/SpiGatewayMessages.java @@ -17,6 +17,7 @@ */ package org.apache.knox.gateway; +import org.apache.http.cookie.Cookie; import org.apache.knox.gateway.i18n.messages.Message; import org.apache.knox.gateway.i18n.messages.MessageLevel; import org.apache.knox.gateway.i18n.messages.Messages; @@ -73,4 +74,8 @@ public interface SpiGatewayMessages { @Message( level = MessageLevel.WARN, text = "Error ocurred while accessing params in query string: {0}" ) void unableToGetParamsFromQueryString(@StackTrace(level=MessageLevel.WARN) Exception e); + + @Message( level = MessageLevel.DEBUG, text = "Accepting service cookie: {0}" ) + void acceptingServiceCookie( Cookie cookie ); + } http://git-wip-us.apache.org/repos/asf/knox/blob/6212381e/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStore.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStore.java b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStore.java index bed8517..1bab384 100644 --- a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStore.java +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStore.java @@ -17,15 +17,126 @@ */ package org.apache.knox.gateway.dispatch; +import java.lang.reflect.Field; +import java.util.Date; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.cookie.BasicClientCookie; +import org.apache.knox.gateway.SpiGatewayMessages; +import org.apache.knox.gateway.i18n.messages.MessagesFactory; public class HadoopAuthCookieStore extends BasicCookieStore { + private static SpiGatewayMessages LOG = MessagesFactory.get( SpiGatewayMessages.class ); + @Override public void addCookie(Cookie cookie) { if (cookie.getName().equals("hadoop.auth") || cookie.getName().equals("hive.server2.auth")) { - super.addCookie(cookie); + Wrapper wrapper = new Wrapper( cookie ); + LOG.acceptingServiceCookie( wrapper ); + super.addCookie( wrapper ); } } -} + + private static class Wrapper extends BasicClientCookie { + + private Cookie delegate; + + Wrapper( Cookie delegate ) { + super( delegate.getName(), delegate.getValue() ); + this.delegate = delegate; + } + + @Override + public String getName() { + return delegate.getName(); + } + + /** + * Checks the cookie value returned by the delegate and wraps it in double quotes if the value isn't + * null, empty or already wrapped in double quotes. + * + * This change is required to workaround Oozie 4.3/Hadoop 2.4 not properly formatting the hadoop.auth cookie. + * See the following jiras for additional context: + * https://issues.apache.org/jira/browse/HADOOP-10710 + * https://issues.apache.org/jira/browse/HADOOP-10379 + * This issue was further compounded by another Oozie issue resulting in Kerberos replay attacks. + * https://issues.apache.org/jira/browse/OOZIE-2427 + */ + @Override + public String getValue() { + String value = delegate.getValue(); + if ( value != null && !value.isEmpty() ) { + if( !value.startsWith( "\"" ) ) { + value = "\"" + value; + } + if( !value.endsWith( "\"" ) ) { + value = value + "\""; + } + } + return value; + } + + @Override + public String getComment() { + return delegate.getComment(); + } + + @Override + public String getCommentURL() { + return delegate.getCommentURL(); + } + + @Override + public Date getExpiryDate() { + return delegate.getExpiryDate(); + } + + @Override + public boolean isPersistent() { + return delegate.isPersistent(); + } + + @Override + public String getDomain() { + return delegate.getDomain(); + } + + @Override + public String getPath() { + return delegate.getPath(); + } + + @Override + public int[] getPorts() { + return delegate.getPorts(); + } + + @Override + public boolean isSecure() { + return delegate.isSecure(); + } + + @Override + public int getVersion() { + return delegate.getVersion(); + } + + @Override + public boolean isExpired( Date date ) { + return delegate.isExpired( date ); + } + + public String toString() { + return (new ReflectionToStringBuilder(this) { + protected boolean accept(Field f) { + return super.accept(f) && !f.getName().equals("delegate"); + } + }).toString(); + } + + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/knox/blob/6212381e/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStoreTest.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStoreTest.java b/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStoreTest.java new file mode 100644 index 0000000..93070d5 --- /dev/null +++ b/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/HadoopAuthCookieStoreTest.java @@ -0,0 +1,73 @@ +/** + * 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.knox.gateway.dispatch; + +import java.util.List; + +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.cookie.BasicClientCookie; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.*; + +public class HadoopAuthCookieStoreTest { + + /** + * Test for the issue reported as KNOX-1171 + * Tests the required to workaround Oozie 4.3/Hadoop 2.4 not properly formatting the hadoop.auth cookie. + * See the following jiras for additional context: + * https://issues.apache.org/jira/browse/HADOOP-10710 + * https://issues.apache.org/jira/browse/HADOOP-10379 + */ + @Test + public void testOozieCookieWorkaroundKnox1171() { + String rawValue = "u=knox&p=knox/[email protected]&t=kerberos&e=1517900515610&s=HpSXUOhoXR/2wXrsgPz5lSbNuf8="; + String quotedValue = "\""+rawValue+"\""; + + HadoopAuthCookieStore store; + List<Cookie> cookies; + Cookie cookie; + + store = new HadoopAuthCookieStore(); + store.addCookie( new BasicClientCookie( "hadoop.auth", rawValue ) ); + cookies = store.getCookies(); + cookie = cookies.get( 0 ); + assertThat( cookie.getValue(), is(quotedValue) ); + + store = new HadoopAuthCookieStore(); + store.addCookie( new BasicClientCookie( "hadoop.auth", quotedValue ) ); + cookies = store.getCookies(); + cookie = cookies.get( 0 ); + assertThat( cookie.getValue(), is(quotedValue) ); + + store = new HadoopAuthCookieStore(); + store.addCookie( new BasicClientCookie( "hadoop.auth", null ) ); + cookies = store.getCookies(); + cookie = cookies.get( 0 ); + assertThat( cookie.getValue(), is(nullValue()) ); + + store = new HadoopAuthCookieStore(); + store.addCookie( new BasicClientCookie( "hadoop.auth", "" ) ); + cookies = store.getCookies(); + cookie = cookies.get( 0 ); + assertThat( cookie.getValue(), is("") ); + } + +} \ No newline at end of file
