HDFS-4564. Ensure webhdfs returns correct HTTP response codes for denied operations. Contributed by Daryn Sharp.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1583241 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3532d96ff6
commit
004d0854b7
@ -349,7 +349,7 @@ public void testDelegationTokenOperations() throws Exception {
|
|||||||
url = new URL(TestJettyHelper.getJettyURL(),
|
url = new URL(TestJettyHelper.getJettyURL(),
|
||||||
"/webhdfs/v1/?op=GETHOMEDIRECTORY&delegation=" + tokenStr);
|
"/webhdfs/v1/?op=GETHOMEDIRECTORY&delegation=" + tokenStr);
|
||||||
conn = (HttpURLConnection) url.openConnection();
|
conn = (HttpURLConnection) url.openConnection();
|
||||||
Assert.assertEquals(HttpURLConnection.HTTP_UNAUTHORIZED,
|
Assert.assertEquals(HttpURLConnection.HTTP_FORBIDDEN,
|
||||||
conn.getResponseCode());
|
conn.getResponseCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,6 +1050,9 @@ BREAKDOWN OF HDFS-5535 ROLLING UPGRADE SUBTASKS AND RELATED JIRAS
|
|||||||
HDFS-6038. Allow JournalNode to handle editlog produced by new release with
|
HDFS-6038. Allow JournalNode to handle editlog produced by new release with
|
||||||
future layoutversion. (jing9)
|
future layoutversion. (jing9)
|
||||||
|
|
||||||
|
HDFS-4564. Ensure webhdfs returns correct HTTP response codes for denied
|
||||||
|
operations. (daryn via acmurthy)
|
||||||
|
|
||||||
Release 2.3.1 - UNRELEASED
|
Release 2.3.1 - UNRELEASED
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
@ -304,6 +304,11 @@ private Path makeAbsolute(Path f) {
|
|||||||
private static Map<?, ?> validateResponse(final HttpOpParam.Op op,
|
private static Map<?, ?> validateResponse(final HttpOpParam.Op op,
|
||||||
final HttpURLConnection conn, boolean unwrapException) throws IOException {
|
final HttpURLConnection conn, boolean unwrapException) throws IOException {
|
||||||
final int code = conn.getResponseCode();
|
final int code = conn.getResponseCode();
|
||||||
|
// server is demanding an authentication we don't support
|
||||||
|
if (code == HttpURLConnection.HTTP_UNAUTHORIZED) {
|
||||||
|
throw new IOException(
|
||||||
|
new AuthenticationException(conn.getResponseMessage()));
|
||||||
|
}
|
||||||
if (code != op.getExpectedHttpResponseCode()) {
|
if (code != op.getExpectedHttpResponseCode()) {
|
||||||
final Map<?, ?> m;
|
final Map<?, ?> m;
|
||||||
try {
|
try {
|
||||||
@ -450,52 +455,33 @@ protected AbstractRunner(final HttpOpParam.Op op, boolean redirected) {
|
|||||||
this.redirected = redirected;
|
this.redirected = redirected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpURLConnection getHttpUrlConnection(final URL url)
|
AbstractRunner run() throws IOException {
|
||||||
throws IOException, AuthenticationException {
|
|
||||||
UserGroupInformation connectUgi = ugi.getRealUser();
|
UserGroupInformation connectUgi = ugi.getRealUser();
|
||||||
if (connectUgi == null) {
|
if (connectUgi == null) {
|
||||||
connectUgi = ugi;
|
connectUgi = ugi;
|
||||||
}
|
}
|
||||||
|
if (op.getRequireAuth()) {
|
||||||
|
connectUgi.checkTGTAndReloginFromKeytab();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
|
// the entire lifecycle of the connection must be run inside the
|
||||||
|
// doAs to ensure authentication is performed correctly
|
||||||
return connectUgi.doAs(
|
return connectUgi.doAs(
|
||||||
new PrivilegedExceptionAction<HttpURLConnection>() {
|
new PrivilegedExceptionAction<AbstractRunner>() {
|
||||||
@Override
|
@Override
|
||||||
public HttpURLConnection run() throws IOException {
|
public AbstractRunner run() throws IOException {
|
||||||
return openHttpUrlConnection(url);
|
return runWithRetry();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException ioe) {
|
|
||||||
Throwable cause = ioe.getCause();
|
|
||||||
if (cause != null && cause instanceof AuthenticationException) {
|
|
||||||
throw (AuthenticationException)cause;
|
|
||||||
}
|
|
||||||
throw ioe;
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpURLConnection openHttpUrlConnection(final URL url)
|
|
||||||
throws IOException {
|
|
||||||
final HttpURLConnection conn;
|
|
||||||
try {
|
|
||||||
conn = (HttpURLConnection) connectionFactory.openConnection(url,
|
|
||||||
op.getRequireAuth());
|
|
||||||
} catch (AuthenticationException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() throws IOException {
|
private void init() throws IOException {
|
||||||
checkRetry = !redirected;
|
checkRetry = !redirected;
|
||||||
URL url = getUrl();
|
URL url = getUrl();
|
||||||
try {
|
conn = (HttpURLConnection) connectionFactory.openConnection(url);
|
||||||
conn = getHttpUrlConnection(url);
|
|
||||||
} catch(AuthenticationException ae) {
|
|
||||||
checkRetry = false;
|
|
||||||
throw new IOException("Authentication failed, url=" + url, ae);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connect() throws IOException {
|
private void connect() throws IOException {
|
||||||
@ -516,7 +502,7 @@ private void disconnect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractRunner run() throws IOException {
|
private AbstractRunner runWithRetry() throws IOException {
|
||||||
/**
|
/**
|
||||||
* Do the real work.
|
* Do the real work.
|
||||||
*
|
*
|
||||||
@ -543,6 +529,10 @@ AbstractRunner run() throws IOException {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
} catch(IOException ioe) {
|
} catch(IOException ioe) {
|
||||||
|
Throwable cause = ioe.getCause();
|
||||||
|
if (cause != null && cause instanceof AuthenticationException) {
|
||||||
|
throw ioe; // no retries for auth failures
|
||||||
|
}
|
||||||
shouldRetry(ioe, retry);
|
shouldRetry(ioe, retry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,9 +77,9 @@ public Response toResponse(Exception e) {
|
|||||||
//Map response status
|
//Map response status
|
||||||
final Response.Status s;
|
final Response.Status s;
|
||||||
if (e instanceof SecurityException) {
|
if (e instanceof SecurityException) {
|
||||||
s = Response.Status.UNAUTHORIZED;
|
s = Response.Status.FORBIDDEN;
|
||||||
} else if (e instanceof AuthorizationException) {
|
} else if (e instanceof AuthorizationException) {
|
||||||
s = Response.Status.UNAUTHORIZED;
|
s = Response.Status.FORBIDDEN;
|
||||||
} else if (e instanceof FileNotFoundException) {
|
} else if (e instanceof FileNotFoundException) {
|
||||||
s = Response.Status.NOT_FOUND;
|
s = Response.Status.NOT_FOUND;
|
||||||
} else if (e instanceof IOException) {
|
} else if (e instanceof IOException) {
|
||||||
|
@ -410,7 +410,7 @@ public void testResponseCode() throws IOException {
|
|||||||
new DoAsParam(ugi.getShortUserName() + "proxy"));
|
new DoAsParam(ugi.getShortUserName() + "proxy"));
|
||||||
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
conn.connect();
|
conn.connect();
|
||||||
assertEquals(HttpServletResponse.SC_UNAUTHORIZED, conn.getResponseCode());
|
assertEquals(HttpServletResponse.SC_FORBIDDEN, conn.getResponseCode());
|
||||||
conn.disconnect();
|
conn.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user