aboutsummaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorzpencer <spencerfang@google.com>2018-09-10 18:06:26 -0700
committerGitHub <noreply@github.com>2018-09-10 18:06:26 -0700
commit8fc84daa303b1805625f6994e79aaea0ed7bedc2 (patch)
treee306ae675b63589bc7cb0989a92cd2888003f0d1 /services
parent98630f187018a0f765f52953a7bab7eb2a1ee534 (diff)
downloadgrpc-grpc-java-8fc84daa303b1805625f6994e79aaea0ed7bedc2.tar.gz
services: remove RequireDoubleSubmitCookieInterceptor (#4833)
The CSRF protection has been moved to the proxy implementation. This is cleaner since the gRPC service should not need to know about grpc-web.
Diffstat (limited to 'services')
-rw-r--r--services/src/main/java/io/grpc/services/ChannelzService.java16
-rw-r--r--services/src/main/java/io/grpc/services/RequireDoubleSubmitCookieInterceptor.java106
-rw-r--r--services/src/test/java/io/grpc/services/RequireDoubleSubmitCookieInterceptorTest.java124
3 files changed, 0 insertions, 246 deletions
diff --git a/services/src/main/java/io/grpc/services/ChannelzService.java b/services/src/main/java/io/grpc/services/ChannelzService.java
index 773c9d4af..b8b3f1fe7 100644
--- a/services/src/main/java/io/grpc/services/ChannelzService.java
+++ b/services/src/main/java/io/grpc/services/ChannelzService.java
@@ -24,8 +24,6 @@ import io.grpc.InternalChannelz.ServerList;
import io.grpc.InternalChannelz.ServerSocketsList;
import io.grpc.InternalChannelz.SocketStats;
import io.grpc.InternalInstrumented;
-import io.grpc.ServerInterceptors;
-import io.grpc.ServerServiceDefinition;
import io.grpc.Status;
import io.grpc.channelz.v1.ChannelzGrpc;
import io.grpc.channelz.v1.GetChannelRequest;
@@ -52,25 +50,11 @@ public final class ChannelzService extends ChannelzGrpc.ChannelzImplBase {
/**
* Creates an instance.
- * @deprecated Call {@link #createInstance(int)}, which includes security interceptors.
*/
- @Deprecated
public static ChannelzService newInstance(int maxPageSize) {
return new ChannelzService(InternalChannelz.instance(), maxPageSize);
}
- /**
- * Creates an instance. The return value may contain built in interceptors for web security.
- *
- * @param maxPageSize the number of items per set of paginated results.
- * @return a {@link ServerServiceDefinition} that represents the channelz service.
- */
- public static ServerServiceDefinition createInstance(int maxPageSize) {
- return ServerInterceptors.intercept(
- new ChannelzService(InternalChannelz.instance(), maxPageSize),
- new RequireDoubleSubmitCookieInterceptor("grpc-channelz-v1-channelz-token"));
- }
-
@VisibleForTesting
ChannelzService(InternalChannelz channelz, int maxPageSize) {
this.channelz = channelz;
diff --git a/services/src/main/java/io/grpc/services/RequireDoubleSubmitCookieInterceptor.java b/services/src/main/java/io/grpc/services/RequireDoubleSubmitCookieInterceptor.java
deleted file mode 100644
index 2347bb521..000000000
--- a/services/src/main/java/io/grpc/services/RequireDoubleSubmitCookieInterceptor.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2018 The gRPC Authors
- *
- * 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 io.grpc.services;
-
-import com.google.common.base.Objects;
-import io.grpc.Metadata;
-import io.grpc.Metadata.Key;
-import io.grpc.ServerCall;
-import io.grpc.ServerCall.Listener;
-import io.grpc.ServerCallHandler;
-import io.grpc.ServerInterceptor;
-import io.grpc.Status;
-import java.net.HttpCookie;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * An interceptor that checks for a double submit cookie, a form of XSRF protection. This
- * interceptor is intended for grpc-web based applications where the web page and grpc-web requests
- * are served from the same origin, namely behind a reverse proxy.
- *
- * <p>This interceptor works by requiring that for each RPC, a pseudo-random value session ID is
- * set as both a cookie as well as a request parameter in the form of a header. We rely on the
- * fact that web browsers only send a cookie when the origin and the cookie domain's
- * match, so RPCs invoked from other places can be detected and blocked.
- *
- * <p>This scheme requires the client app and server cooperate, and this interceptor implements
- * only the server side logic.
- *
- * <p>On the client side, the application is responsible for setting the cookie and the header.
- */
-final class RequireDoubleSubmitCookieInterceptor implements ServerInterceptor {
- private static final Logger log
- = Logger.getLogger(RequireDoubleSubmitCookieInterceptor.class.getName());
-
- static final Key<String> COOKIE = Key.of("cookie", Metadata.ASCII_STRING_MARSHALLER);
-
- @SuppressWarnings("rawtypes")
- static final ServerCall.Listener NOOP = new ServerCall.Listener() {};
-
- private final String tokenName;
- private final Key<String> headerKey;
- private final Status failStatus;
-
- RequireDoubleSubmitCookieInterceptor(String tokenName) {
- this.tokenName = tokenName;
- headerKey = Key.of(tokenName, Metadata.ASCII_STRING_MARSHALLER);
- failStatus
- = Status.FAILED_PRECONDITION.withDescription(
- String.format("Double submit cookie failure. There must be both a cookie and "
- + "metadata with matching values, for XSRF protection. "
- + "The cookie and metadata keys must both be: %s", tokenName));
- }
-
- @SuppressWarnings("unchecked")
- private <ReqT, RespT> Listener<ReqT> failCall(ServerCall<ReqT, RespT> call) {
- call.close(failStatus, new Metadata());
- return NOOP;
- }
-
- @Override
- public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers,
- ServerCallHandler<ReqT, RespT> next) {
- String xsrfCookie = null;
- Iterable<String> cookieHeaders = headers.getAll(COOKIE);
- if (cookieHeaders == null) {
- return failCall(call);
- }
- for (String cookieHeader : cookieHeaders) {
- try {
- for (HttpCookie cookie : HttpCookie.parse(cookieHeader)) {
- if (cookie.getName().equals(tokenName)) {
- if (xsrfCookie == null) {
- xsrfCookie = cookie.getValue();
- } else {
- log.log(Level.FINE, "Multiple cookies set for {}, this is not allowed", tokenName);
- return failCall(call);
- }
- }
- }
- } catch (IllegalArgumentException e) {
- log.log(Level.FINE, "Failed to parse cookie header", e);
- return failCall(call);
- }
- }
- String xsrfHeader = headers.get(headerKey);
- if (xsrfCookie == null || !Objects.equal(xsrfCookie, xsrfHeader)) {
- return failCall(call);
- }
- return next.startCall(call, headers);
- }
-}
diff --git a/services/src/test/java/io/grpc/services/RequireDoubleSubmitCookieInterceptorTest.java b/services/src/test/java/io/grpc/services/RequireDoubleSubmitCookieInterceptorTest.java
deleted file mode 100644
index d6874d1f2..000000000
--- a/services/src/test/java/io/grpc/services/RequireDoubleSubmitCookieInterceptorTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2018 The gRPC Authors
- *
- * 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 io.grpc.services;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-
-import io.grpc.Metadata;
-import io.grpc.MethodDescriptor;
-import io.grpc.ServerCall;
-import io.grpc.ServerCall.Listener;
-import io.grpc.ServerCallHandler;
-import io.grpc.Status;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Unit tests for {@link RequireDoubleSubmitCookieInterceptor}. */
-@RunWith(JUnit4.class)
-public final class RequireDoubleSubmitCookieInterceptorTest {
- private static final String XSRF_TOKEN_VALUE = "abc123";
- private static final ServerCall.Listener<Void> NEXT_LISTENER = new ServerCall.Listener<Void>() {};
- private static final ServerCallHandler<Void, Void> NEXT = new ServerCallHandler<Void, Void>() {
- @Override
- public Listener<Void> startCall(ServerCall<Void, Void> call, Metadata headers) {
- return NEXT_LISTENER;
- }
- };
-
- private Status closeStatus;
- private final ServerCall<Void, Void> call = new ServerCall<Void, Void>() {
- @Override
- public void close(Status status, Metadata trailers) {
- closeStatus = status;
- }
-
- @Override
- public void request(int numMessages) {}
-
- @Override
- public void sendHeaders(Metadata headers) {}
-
- @Override
- public void sendMessage(Void message) {}
-
- @Override
- public boolean isCancelled() {
- return false;
- }
-
- @Override
- public MethodDescriptor<Void, Void> getMethodDescriptor() {
- return null;
- }
- };
-
- private final RequireDoubleSubmitCookieInterceptor interceptor
- = new RequireDoubleSubmitCookieInterceptor("test-xsrf-token");
- private final Metadata.Key<String> xsrfHeader
- = Metadata.Key.of("test-xsrf-token", Metadata.ASCII_STRING_MARSHALLER);
-
- @Test
- public void noCookieNoHeader() throws Exception {
- Metadata headers = new Metadata();
- Listener<Void> listener = interceptor.interceptCall(call, headers, NEXT);
- assertSame(RequireDoubleSubmitCookieInterceptor.NOOP, listener);
- assertEquals(Status.FAILED_PRECONDITION.getCode(), closeStatus.getCode());
- }
-
- @Test
- public void noHeader() throws Exception {
- Metadata headers = new Metadata();
- Listener<Void> listener = interceptor.interceptCall(call, headers, NEXT);
- headers.put(RequireDoubleSubmitCookieInterceptor.COOKIE, "test-xsrf-token=" + XSRF_TOKEN_VALUE);
- assertSame(RequireDoubleSubmitCookieInterceptor.NOOP, listener);
- assertEquals(Status.FAILED_PRECONDITION.getCode(), closeStatus.getCode());
- }
-
- @Test
- public void noCookie() throws Exception {
- Metadata headers = new Metadata();
- Listener<Void> listener = interceptor.interceptCall(call, headers, NEXT);
- headers.put(xsrfHeader, XSRF_TOKEN_VALUE);
- assertSame(RequireDoubleSubmitCookieInterceptor.NOOP, listener);
- assertEquals(Status.FAILED_PRECONDITION.getCode(), closeStatus.getCode());
- }
-
- @Test
- public void matchingCookieAndHeader() throws Exception {
- Metadata headers = new Metadata();
- headers.put(
- RequireDoubleSubmitCookieInterceptor.COOKIE, "test-xsrf-token=" + XSRF_TOKEN_VALUE);
- headers.put(xsrfHeader, XSRF_TOKEN_VALUE);
- Listener<Void> listener = interceptor.interceptCall(call, headers, NEXT);
- assertSame(NEXT_LISTENER, listener);
- assertNull(closeStatus);
- }
-
- @Test
- public void mismatchedCookieAndHeader() throws Exception {
- Metadata headers = new Metadata();
- headers.put(
- RequireDoubleSubmitCookieInterceptor.COOKIE, "test-xsrf-token=" + XSRF_TOKEN_VALUE);
- headers.put(xsrfHeader, "foobar");
- Listener<Void> listener = interceptor.interceptCall(call, headers, NEXT);
- assertSame(RequireDoubleSubmitCookieInterceptor.NOOP, listener);
- assertEquals(Status.FAILED_PRECONDITION.getCode(), closeStatus.getCode());
- }
-}