Convert RegistrarServlet to RegistrarAction

Convert to an action and remove ResourceServlet, JsonTransportServlet and
JsonTransportServlet, all of which exist only to support it.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=137519385
This commit is contained in:
mmuller 2016-10-28 09:32:24 -07:00 committed by Ben McIlwain
parent 2e4273c4f4
commit bbd20ec71d
24 changed files with 330 additions and 858 deletions

View file

@ -28,16 +28,3 @@ java_library(
"//java/google/registry/util",
],
)
java_library(
name = "servlets",
srcs = glob(["*Servlet.java"]),
deps = [
":security",
"//java/com/google/common/base",
"//third_party/java/appengine:appengine-api",
"//third_party/java/joda_time",
"//third_party/java/servlet/servlet_api",
"//java/google/registry/request",
],
)

View file

@ -1,74 +0,0 @@
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
//
// 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.
package google.registry.security;
import static com.google.common.base.Preconditions.checkNotNull;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import google.registry.request.HttpException;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Secure servlet that speaks JSON for both input and output.
*
* <p>This servlet accepts only JSON inputs (using the payload) and returns only JSON
* responses, using and various security best practices such as a parser breaker,
* {@code Content-Disposition: attachment}, etc.
*
* @see JsonHttp
*/
public abstract class JsonTransportServlet extends XsrfProtectedServlet {
protected JsonTransportServlet(String xsrfScope, boolean requireAdmin) {
super(xsrfScope, requireAdmin);
}
/**
* Verify that this is a well-formed request and then execute it. A well-formed request will have
* either a JSON string in the "json" param that evaluates to a map, or nothing in "json".
*/
@Override
protected final void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
Map<String, ?> input = JsonHttp.read(req);
if (input == null) {
rsp.sendError(SC_BAD_REQUEST, "Malformed JSON");
return;
}
Map<String, ?> output;
try {
output = doJsonPost(req, input);
} catch (HttpException e) {
e.send(rsp);
return;
}
checkNotNull(output, "doJsonPost() returned null");
rsp.setStatus(SC_OK);
JsonHttp.write(rsp, output);
}
/**
* Handler for HTTP POST requests.
*
* @param req Servlet request object.
* @param input JSON request object or empty if none was provided.
* @return an arbitrary JSON object. Must not be {@code null}.
* @throws HttpException in order to send a non-200 status code / message to the client.
*/
public abstract Map<String, Object> doJsonPost(HttpServletRequest req, Map<String, ?> input);
}

View file

@ -1,83 +0,0 @@
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
//
// 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.
package google.registry.security;
import static com.google.appengine.api.users.UserServiceFactory.getUserService;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.nullToEmpty;
import static google.registry.security.XsrfTokenManager.X_CSRF_TOKEN;
import static google.registry.security.XsrfTokenManager.validateToken;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import com.google.appengine.api.users.UserService;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.joda.time.Duration;
/**
* Servlet with Cross-Site Request Forgery (XSRF) protection.
*
* <p>This servlet enforces XSRF protection on all requests by checking the value provided in the
* "X-CSRF-Token" header. It can also optionally enforce that only admin users can call it.
*
* <p>All servlets that handle client requests should use XSRF protection.
*/
public abstract class XsrfProtectedServlet extends HttpServlet {
private static final Duration XSRF_VALIDITY = Duration.standardDays(1);
/** Used to validate XSRF tokens. */
private String xsrfScope;
/** Whether to do a security check for admin status. */
private boolean requireAdmin;
/** Gets the XSRF scope for this servlet. */
public String getScope() {
return xsrfScope;
}
protected XsrfProtectedServlet(String xsrfScope, boolean requireAdmin) {
this.xsrfScope = checkNotNull(xsrfScope);
this.requireAdmin = requireAdmin;
}
@Override
public final void service(HttpServletRequest req, HttpServletResponse rsp)
throws IOException, ServletException {
if (!validateToken(nullToEmpty(req.getHeader(X_CSRF_TOKEN)), xsrfScope, XSRF_VALIDITY)) {
rsp.sendError(SC_FORBIDDEN, "Invalid " + X_CSRF_TOKEN);
return;
}
if (!validateAdmin()) {
rsp.sendError(SC_FORBIDDEN, "Administrator access only");
return;
}
doPost(req, rsp);
}
/**
* If this is an admin-only servlet, require admin permissions or being in development mode. Such
* servlets should primarily be defended by being marked internal-only in web.xml, but it's worth
* adding a defense-in-depth.
*/
private boolean validateAdmin() {
UserService userService = getUserService();
return requireAdmin ? (userService.isUserLoggedIn() && userService.isUserAdmin()) : true;
}
}