geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bschucha...@apache.org
Subject [46/48] geode git commit: GEODE-3447 Implement client authorization for the new protocol
Date Tue, 22 Aug 2017 22:36:48 GMT
GEODE-3447 Implement client authorization for the new protocol

Implementation of authorization checks for the new protocol.


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/a2b678aa
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/a2b678aa
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/a2b678aa

Branch: refs/heads/feature/GEODE-3447
Commit: a2b678aa06af73d218da6e9ae8d95f2942d23a7b
Parents: c0f6c84
Author: Bruce Schuchardt <bschuchardt@pivotal.io>
Authored: Thu Aug 17 15:22:57 2017 -0700
Committer: Bruce Schuchardt <bschuchardt@pivotal.io>
Committed: Tue Aug 22 14:46:13 2017 -0700

----------------------------------------------------------------------
 .../sockets/ClientProtocolMessageHandler.java   |   3 +
 .../geode/security/NoOpStreamAuthenticator.java |   7 +-
 .../geode/security/NoOpStreamAuthorizer.java    |  26 +++
 .../geode/security/StreamAuthenticator.java     |  10 +-
 .../apache/geode/security/StreamAuthorizer.java |   8 +
 .../GenericProtocolServerConnectionTest.java    |   2 +-
 .../protocol/protobuf/OperationContext.java     |  10 +-
 .../protocol/protobuf/ProtobufOpsProcessor.java |  10 +
 .../protobuf/ProtobufSimpleAuthenticator.java   |  18 +-
 .../protobuf/ProtobufSimpleAuthorizer.java      |  42 ++++
 .../protobuf/ProtobufStreamProcessor.java       |   1 +
 .../registry/OperationContextRegistry.java      |  39 +++-
 .../protocol/AuthorizationIntegrationTest.java  | 205 +++++++++++++++++++
 .../protobuf/ProtobufStreamProcessorTest.java   |   1 +
 14 files changed, 361 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientProtocolMessageHandler.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientProtocolMessageHandler.java
b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientProtocolMessageHandler.java
index 0ced3aa..0d1dfd9 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientProtocolMessageHandler.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientProtocolMessageHandler.java
@@ -15,6 +15,9 @@
 
 package org.apache.geode.internal.cache.tier.sockets;
 
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.security.StreamAuthorizer;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthenticator.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthenticator.java
b/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthenticator.java
index 0a6dde1..62f49fe 100644
--- a/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthenticator.java
+++ b/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthenticator.java
@@ -23,8 +23,6 @@ import java.io.OutputStream;
  * returns true.
  */
 public class NoOpStreamAuthenticator implements StreamAuthenticator {
-
-
   @Override
   public void receiveMessage(InputStream inputStream, OutputStream outputStream,
       SecurityManager securityManager) throws IOException {
@@ -37,6 +35,11 @@ public class NoOpStreamAuthenticator implements StreamAuthenticator {
   }
 
   @Override
+  public StreamAuthorizer getAuthorizer() {
+    return new NoOpStreamAuthorizer();
+  }
+
+  @Override
   public String implementationID() {
     return "NOOP";
   }

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthorizer.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthorizer.java
b/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthorizer.java
new file mode 100644
index 0000000..1b21576
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/security/NoOpStreamAuthorizer.java
@@ -0,0 +1,26 @@
+/*
+ * 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.geode.security;
+
+/**
+ * An implementation of {@link StreamAuthorizer} that doesn't use its parameters and always
returns
+ * true.
+ */
+public class NoOpStreamAuthorizer implements StreamAuthorizer {
+  @Override
+  public boolean authorize(ResourcePermission permissionRequested) {
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-core/src/main/java/org/apache/geode/security/StreamAuthenticator.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/security/StreamAuthenticator.java b/geode-core/src/main/java/org/apache/geode/security/StreamAuthenticator.java
index 7db1a2b..5cbc4f8 100644
--- a/geode-core/src/main/java/org/apache/geode/security/StreamAuthenticator.java
+++ b/geode-core/src/main/java/org/apache/geode/security/StreamAuthenticator.java
@@ -14,8 +14,6 @@
  */
 package org.apache.geode.security;
 
-import org.apache.geode.security.SecurityManager;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -46,6 +44,14 @@ public interface StreamAuthenticator {
   boolean isAuthenticated();
 
   /**
+   * Return an authorization object which can be used to determine which permissions this
stream has
+   * according to the provided securityManager.
+   *
+   * Calling this before authentication has succeeded may result in a null return object.
+   */
+  StreamAuthorizer getAuthorizer();
+
+  /**
    * @return a unique identifier for this particular implementation (NOOP, PASSTHROUGH, etc.)
    */
   String implementationID();

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-core/src/main/java/org/apache/geode/security/StreamAuthorizer.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/security/StreamAuthorizer.java b/geode-core/src/main/java/org/apache/geode/security/StreamAuthorizer.java
new file mode 100644
index 0000000..c6cef33
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/security/StreamAuthorizer.java
@@ -0,0 +1,8 @@
+package org.apache.geode.security;
+
+/**
+ * Created by bschuchardt on 8/17/17.
+ */
+public interface StreamAuthorizer {
+  boolean authorize(ResourcePermission permissionRequested);
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java
b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java
index 383fbf0..6817b13 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/GenericProtocolServerConnectionTest.java
@@ -53,7 +53,7 @@ public class GenericProtocolServerConnectionTest {
     when(socketMock.getInetAddress()).thenReturn(InetAddress.getByName("localhost"));
 
     ClientProtocolMessageHandler clientProtocolMock = mock(ClientProtocolMessageHandler.class);
-    doThrow(new IOException()).when(clientProtocolMock).receiveMessage(any(), any(), any());
+    doThrow(new IOException()).when(clientProtocolMock).receiveMessage(any(), any(), any(),
any());
 
     return new GenericProtocolServerConnection(socketMock, mock(InternalCache.class),
         mock(CachedRegionHelper.class), mock(CacheServerStats.class), 0, 0, "",

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/OperationContext.java
----------------------------------------------------------------------
diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/OperationContext.java
b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/OperationContext.java
index 5191007..488dfc4 100644
--- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/OperationContext.java
+++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/OperationContext.java
@@ -19,6 +19,7 @@ import java.util.function.Function;
 
 import org.apache.geode.annotations.Experimental;
 import org.apache.geode.protocol.operations.OperationHandler;
+import org.apache.geode.security.ResourcePermission;
 
 @Experimental
 public class OperationContext<OperationRequest, OperationResponse> {
@@ -26,14 +27,17 @@ public class OperationContext<OperationRequest, OperationResponse>
{
   private final Function<ClientProtocol.Request, OperationRequest> fromRequest;
   private final Function<OperationResponse, ClientProtocol.Response.Builder> toResponse;
   private final Function<BasicTypes.ErrorResponse, ClientProtocol.Response.Builder>
toErrorResponse;
+  private final ResourcePermission accessPermissionRequired;
 
   public OperationContext(Function<ClientProtocol.Request, OperationRequest> fromRequest,
       OperationHandler<OperationRequest, OperationResponse> operationHandler,
-      Function<OperationResponse, ClientProtocol.Response.Builder> toResponse) {
+      Function<OperationResponse, ClientProtocol.Response.Builder> toResponse,
+      ResourcePermission permissionRequired) {
     this.operationHandler = operationHandler;
     this.fromRequest = fromRequest;
     this.toResponse = toResponse;
     this.toErrorResponse = OperationContext::makeErrorBuilder;
+    accessPermissionRequired = permissionRequired;
   }
 
   public static ClientProtocol.Response.Builder makeErrorBuilder(
@@ -56,4 +60,8 @@ public class OperationContext<OperationRequest, OperationResponse>
{
   public Function<BasicTypes.ErrorResponse, ClientProtocol.Response.Builder> getToErrorResponse()
{
     return toErrorResponse;
   }
+
+  public ResourcePermission getAccessPermissionRequired() {
+    return accessPermissionRequired;
+  }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java
----------------------------------------------------------------------
diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java
b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java
index 3619e0d..43601d7 100644
--- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java
+++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufOpsProcessor.java
@@ -19,6 +19,7 @@ import org.apache.geode.internal.cache.tier.sockets.MessageExecutionContext;
 import org.apache.geode.internal.cache.tier.sockets.InvalidExecutionContextException;
 import org.apache.geode.protocol.protobuf.registry.OperationContextRegistry;
 import org.apache.geode.protocol.protobuf.utilities.ProtobufResponseUtilities;
+import org.apache.geode.security.StreamAuthorizer;
 import org.apache.geode.serialization.SerializationService;
 
 /**
@@ -51,6 +52,15 @@ public class ProtobufOpsProcessor {
           ProtocolErrorCode.UNSUPPORTED_OPERATION.codeValue,
           "Invalid execution context found for operation."));
     }
+    Result result;
+    if (authorizer.authorize(operationContext.getAccessPermissionRequired())) {
+      result = operationContext.getOperationHandler().process(serializationService,
+          operationContext.getFromRequest().apply(request), cache);
+    } else {
+      result = Failure.of(ProtobufResponseUtilities.makeErrorResponse(
+          ProtocolErrorCode.AUTHORIZATION_FAILED.codeValue,
+          "User isn't authorized for this operation."));
+    }
 
     builder = (ClientProtocol.Response.Builder) result.map(operationContext.getToResponse(),
         operationContext.getToErrorResponse());

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthenticator.java
----------------------------------------------------------------------
diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthenticator.java
b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthenticator.java
index 00285bb..4b702ea 100644
--- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthenticator.java
+++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthenticator.java
@@ -18,6 +18,7 @@ import org.apache.geode.management.internal.security.ResourceConstants;
 import org.apache.geode.security.StreamAuthenticator;
 import org.apache.geode.security.AuthenticationFailedException;
 import org.apache.geode.security.SecurityManager;
+import org.apache.geode.security.StreamAuthorizer;
 
 import java.io.EOFException;
 import java.io.IOException;
@@ -27,6 +28,7 @@ import java.util.Properties;
 
 public class ProtobufSimpleAuthenticator implements StreamAuthenticator {
   private boolean authenticated;
+  private ProtobufSimpleAuthorizer authorizer = null;
 
   @Override
   public void receiveMessage(InputStream inputStream, OutputStream outputStream,
@@ -41,20 +43,28 @@ public class ProtobufSimpleAuthenticator implements StreamAuthenticator
{
     properties.setProperty(ResourceConstants.USER_NAME, authenticationRequest.getUsername());
     properties.setProperty(ResourceConstants.PASSWORD, authenticationRequest.getPassword());
 
+    authorizer = null; // authenticating a new user clears current authorizer
     try {
       Object principal = securityManager.authenticate(properties);
-      authenticated = principal != null;
+      if (principal != null) {
+        authorizer = new ProtobufSimpleAuthorizer(principal, securityManager);
+      }
     } catch (AuthenticationFailedException e) {
-      authenticated = false;
+      authorizer = null;
     }
 
-    AuthenticationAPI.SimpleAuthenticationResponse.newBuilder().setAuthenticated(authenticated)
+    AuthenticationAPI.SimpleAuthenticationResponse.newBuilder().setAuthenticated(isAuthenticated())
         .build().writeDelimitedTo(outputStream);
   }
 
   @Override
   public boolean isAuthenticated() {
-    return authenticated;
+    return authorizer != null;
+  }
+
+  @Override
+  public StreamAuthorizer getAuthorizer() {
+    return authorizer;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthorizer.java
----------------------------------------------------------------------
diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthorizer.java
b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthorizer.java
new file mode 100644
index 0000000..872632a
--- /dev/null
+++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufSimpleAuthorizer.java
@@ -0,0 +1,42 @@
+/*
+ * 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.geode.protocol.protobuf;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Properties;
+
+import org.apache.geode.security.AuthenticationFailedException;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.SecurityManager;
+import org.apache.geode.security.StreamAuthenticator;
+import org.apache.geode.security.StreamAuthorizer;
+
+public class ProtobufSimpleAuthorizer implements StreamAuthorizer {
+  private final Object authenticatedPrincipal;
+  private final SecurityManager securityManager;
+
+  public ProtobufSimpleAuthorizer(Object authenticatedPrincipal, SecurityManager securityManager)
{
+    this.authenticatedPrincipal = authenticatedPrincipal;
+    this.securityManager = securityManager;
+  }
+
+  @Override
+  public boolean authorize(ResourcePermission permissionRequested) {
+    return securityManager.authorize(authenticatedPrincipal, permissionRequested);
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java
----------------------------------------------------------------------
diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java
b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java
index accb899..8f39cd5 100644
--- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java
+++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessor.java
@@ -26,6 +26,7 @@ import org.apache.geode.protocol.exception.InvalidProtocolMessageException;
 import org.apache.geode.protocol.protobuf.registry.OperationContextRegistry;
 import org.apache.geode.protocol.protobuf.serializer.ProtobufProtocolSerializer;
 import org.apache.geode.protocol.protobuf.utilities.ProtobufUtilities;
+import org.apache.geode.security.StreamAuthorizer;
 import org.apache.geode.serialization.registry.exception.CodecAlreadyRegisteredForTypeException;
 
 /**

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/registry/OperationContextRegistry.java
----------------------------------------------------------------------
diff --git a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/registry/OperationContextRegistry.java
b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/registry/OperationContextRegistry.java
index dfe975c..6b541eb 100644
--- a/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/registry/OperationContextRegistry.java
+++ b/geode-protobuf/src/main/java/org/apache/geode/protocol/protobuf/registry/OperationContextRegistry.java
@@ -30,6 +30,7 @@ import org.apache.geode.protocol.protobuf.operations.GetRequestOperationHandler;
 import org.apache.geode.protocol.protobuf.operations.PutAllRequestOperationHandler;
 import org.apache.geode.protocol.protobuf.operations.PutRequestOperationHandler;
 import org.apache.geode.protocol.protobuf.operations.RemoveRequestOperationHandler;
+import org.apache.geode.security.ResourcePermission;
 
 @Experimental
 public class OperationContextRegistry {
@@ -47,41 +48,57 @@ public class OperationContextRegistry {
     operationContexts.put(RequestAPICase.GETREQUEST,
         new OperationContext<>(ClientProtocol.Request::getGetRequest,
             new GetRequestOperationHandler(),
-            opsResp -> ClientProtocol.Response.newBuilder().setGetResponse(opsResp)));
+            opsResp -> ClientProtocol.Response.newBuilder().setGetResponse(opsResp),
+            new ResourcePermission(ResourcePermission.Resource.DATA,
+                ResourcePermission.Operation.READ)));
 
     operationContexts.put(RequestAPICase.GETALLREQUEST,
         new OperationContext<>(ClientProtocol.Request::getGetAllRequest,
             new GetAllRequestOperationHandler(),
-            opsResp -> ClientProtocol.Response.newBuilder().setGetAllResponse(opsResp)));
+            opsResp -> ClientProtocol.Response.newBuilder().setGetAllResponse(opsResp),
+            new ResourcePermission(ResourcePermission.Resource.DATA,
+                ResourcePermission.Operation.READ)));
 
     operationContexts.put(RequestAPICase.PUTREQUEST,
         new OperationContext<>(ClientProtocol.Request::getPutRequest,
             new PutRequestOperationHandler(),
-            opsResp -> ClientProtocol.Response.newBuilder().setPutResponse(opsResp)));
+            opsResp -> ClientProtocol.Response.newBuilder().setPutResponse(opsResp),
+            new ResourcePermission(ResourcePermission.Resource.DATA,
+                ResourcePermission.Operation.WRITE)));
 
     operationContexts.put(RequestAPICase.PUTALLREQUEST,
         new OperationContext<>(ClientProtocol.Request::getPutAllRequest,
             new PutAllRequestOperationHandler(),
-            opsResp -> ClientProtocol.Response.newBuilder().setPutAllResponse(opsResp)));
+            opsResp -> ClientProtocol.Response.newBuilder().setPutAllResponse(opsResp),
+            new ResourcePermission(ResourcePermission.Resource.DATA,
+                ResourcePermission.Operation.WRITE)));
 
     operationContexts.put(RequestAPICase.REMOVEREQUEST,
         new OperationContext<>(ClientProtocol.Request::getRemoveRequest,
             new RemoveRequestOperationHandler(),
-            opsResp -> ClientProtocol.Response.newBuilder().setRemoveResponse(opsResp)));
+            opsResp -> ClientProtocol.Response.newBuilder().setRemoveResponse(opsResp),
+            new ResourcePermission(ResourcePermission.Resource.DATA,
+                ResourcePermission.Operation.WRITE)));
 
     operationContexts.put(RequestAPICase.GETREGIONNAMESREQUEST,
         new OperationContext<>(ClientProtocol.Request::getGetRegionNamesRequest,
             new GetRegionNamesRequestOperationHandler(),
-            opsResp -> ClientProtocol.Response.newBuilder().setGetRegionNamesResponse(opsResp)));
+            opsResp -> ClientProtocol.Response.newBuilder().setGetRegionNamesResponse(opsResp),
+            new ResourcePermission(ResourcePermission.Resource.DATA,
+                ResourcePermission.Operation.READ)));
 
     operationContexts.put(RequestAPICase.GETREGIONREQUEST,
         new OperationContext<>(ClientProtocol.Request::getGetRegionRequest,
             new GetRegionRequestOperationHandler(),
-            opsResp -> ClientProtocol.Response.newBuilder().setGetRegionResponse(opsResp)));
+            opsResp -> ClientProtocol.Response.newBuilder().setGetRegionResponse(opsResp),
+            new ResourcePermission(ResourcePermission.Resource.DATA,
+                ResourcePermission.Operation.READ)));
 
-    operationContexts.put(RequestAPICase.GETAVAILABLESERVERSREQUEST, new OperationContext<>(
-        ClientProtocol.Request::getGetAvailableServersRequest,
-        new GetAvailableServersOperationHandler(),
-        opsResp -> ClientProtocol.Response.newBuilder().setGetAvailableServersResponse(opsResp)));
+    operationContexts.put(RequestAPICase.GETAVAILABLESERVERSREQUEST,
+        new OperationContext<>(ClientProtocol.Request::getGetAvailableServersRequest,
+            new GetAvailableServersOperationHandler(),
+            opsResp -> ClientProtocol.Response.newBuilder().setGetAvailableServersResponse(opsResp),
+            new ResourcePermission(ResourcePermission.Resource.CLUSTER,
+                ResourcePermission.Operation.READ)));
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-protobuf/src/test/java/org/apache/geode/protocol/AuthorizationIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-protobuf/src/test/java/org/apache/geode/protocol/AuthorizationIntegrationTest.java
b/geode-protobuf/src/test/java/org/apache/geode/protocol/AuthorizationIntegrationTest.java
new file mode 100644
index 0000000..9df23d6
--- /dev/null
+++ b/geode-protobuf/src/test/java/org/apache/geode/protocol/AuthorizationIntegrationTest.java
@@ -0,0 +1,205 @@
+/*
+ * 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.geode.protocol;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import org.awaitility.Awaitility;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.server.CacheServer;
+import org.apache.geode.internal.AvailablePortHelper;
+import org.apache.geode.protocol.protobuf.AuthenticationAPI;
+import org.apache.geode.protocol.protobuf.ClientProtocol;
+import org.apache.geode.protocol.protobuf.ProtobufSerializationService;
+import org.apache.geode.protocol.protobuf.ProtocolErrorCode;
+import org.apache.geode.protocol.protobuf.RegionAPI;
+import org.apache.geode.protocol.protobuf.serializer.ProtobufProtocolSerializer;
+import org.apache.geode.protocol.protobuf.utilities.ProtobufUtilities;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.SecurityManager;
+import org.apache.geode.serialization.registry.exception.CodecAlreadyRegisteredForTypeException;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+
+@Category(IntegrationTest.class)
+public class AuthorizationIntegrationTest {
+
+  private static final String TEST_USERNAME = "bob";
+  private static final String TEST_PASSWORD = "bobspassword";
+  public static final String TEST_REGION = "testRegion";
+
+  @Rule
+  public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+  private Cache cache;
+  private int cacheServerPort;
+  private CacheServer cacheServer;
+  private Socket socket;
+  private OutputStream outputStream;
+  private ProtobufSerializationService serializationService;
+  private InputStream inputStream;
+  private ProtobufProtocolSerializer protobufProtocolSerializer;
+  private Object securityPrincipal;
+  private SecurityManager mockSecurityManager;
+  private String testRegion;
+  public static final ResourcePermission READ_PERMISSION =
+      new ResourcePermission(ResourcePermission.Resource.DATA, ResourcePermission.Operation.READ);
+  public static final ResourcePermission WRITE_PERMISSION =
+      new ResourcePermission(ResourcePermission.Resource.DATA, ResourcePermission.Operation.WRITE);
+
+  @Before
+  public void setUp() throws IOException, CodecAlreadyRegisteredForTypeException {
+    Properties expectedAuthProperties = new Properties();
+    expectedAuthProperties.setProperty("username", TEST_USERNAME);
+    expectedAuthProperties.setProperty("password", TEST_PASSWORD);
+
+    securityPrincipal = new Object();
+    mockSecurityManager = mock(SecurityManager.class);
+    when(mockSecurityManager.authenticate(expectedAuthProperties)).thenReturn(securityPrincipal);
+
+    Properties properties = new Properties();
+    CacheFactory cacheFactory = new CacheFactory(properties);
+    cacheFactory.set("mcast-port", "0"); // sometimes it isn't due to other tests.
+
+    cacheFactory.setSecurityManager(mockSecurityManager);
+    cache = cacheFactory.create();
+
+    cacheServer = cache.addCacheServer();
+    cacheServerPort = AvailablePortHelper.getRandomAvailableTCPPort();
+    cacheServer.setPort(cacheServerPort);
+    cacheServer.start();
+
+    cache.createRegionFactory().create(TEST_REGION);
+
+    System.setProperty("geode.feature-protobuf-protocol", "true");
+    System.setProperty("geode.protocol-authentication-mode", "SIMPLE");
+    socket = new Socket("localhost", cacheServerPort);
+
+    Awaitility.await().atMost(5, TimeUnit.SECONDS).until(socket::isConnected);
+    outputStream = socket.getOutputStream();
+    inputStream = socket.getInputStream();
+    outputStream.write(110);
+
+    serializationService = new ProtobufSerializationService();
+    protobufProtocolSerializer = new ProtobufProtocolSerializer();
+
+    when(mockSecurityManager.authorize(same(securityPrincipal), any())).thenReturn(false);
+    AuthenticationAPI.SimpleAuthenticationRequest authenticationRequest =
+        AuthenticationAPI.SimpleAuthenticationRequest.newBuilder().setUsername(TEST_USERNAME)
+            .setPassword(TEST_PASSWORD).build();
+    authenticationRequest.writeDelimitedTo(outputStream);
+
+    AuthenticationAPI.SimpleAuthenticationResponse authenticationResponse =
+        AuthenticationAPI.SimpleAuthenticationResponse.parseDelimitedFrom(inputStream);
+    assertTrue(authenticationResponse.getAuthenticated());
+  }
+
+  @After
+  public void shutDown() throws IOException {
+    cache.close();
+    socket.close();
+  }
+
+
+  @Test
+  public void validateNoPermissions() throws Exception {
+    when(mockSecurityManager.authorize(securityPrincipal, READ_PERMISSION)).thenReturn(false);
+    when(mockSecurityManager.authorize(securityPrincipal, WRITE_PERMISSION)).thenReturn(false);
+
+    verifyOperations(false, false);
+  }
+
+  @Test
+  public void validateWritePermission() throws Exception {
+    when(mockSecurityManager.authorize(securityPrincipal, READ_PERMISSION)).thenReturn(false);
+    when(mockSecurityManager.authorize(securityPrincipal, WRITE_PERMISSION)).thenReturn(true);
+
+    verifyOperations(false, true);
+  }
+
+  @Test
+  public void validateReadPermission() throws Exception {
+    when(mockSecurityManager.authorize(securityPrincipal, READ_PERMISSION)).thenReturn(true);
+    when(mockSecurityManager.authorize(securityPrincipal, WRITE_PERMISSION)).thenReturn(false);
+
+    verifyOperations(true, false);
+  }
+
+  @Test
+  public void validateReadAndWritePermission() throws Exception {
+    when(mockSecurityManager.authorize(securityPrincipal, READ_PERMISSION)).thenReturn(true);
+    when(mockSecurityManager.authorize(securityPrincipal, WRITE_PERMISSION)).thenReturn(true);
+
+    verifyOperations(true, true);
+  }
+
+  private void verifyOperations(boolean readAllowed, boolean writeAllowed) throws Exception
{
+    ClientProtocol.Message getRegionsMessage =
+        ClientProtocol.Message.newBuilder().setRequest(ClientProtocol.Request.newBuilder()
+            .setGetRegionNamesRequest(RegionAPI.GetRegionNamesRequest.newBuilder())).build();
+    validateOperationAuthorized(getRegionsMessage, inputStream, outputStream,
+        readAllowed ? ClientProtocol.Response.ResponseAPICase.GETREGIONNAMESRESPONSE
+            : ClientProtocol.Response.ResponseAPICase.ERRORRESPONSE);
+
+    ClientProtocol.Message putMessage = ClientProtocol.Message.newBuilder()
+        .setRequest(ClientProtocol.Request.newBuilder()
+            .setPutRequest(RegionAPI.PutRequest.newBuilder().setRegionName(TEST_REGION).setEntry(
+                ProtobufUtilities.createEntry(serializationService, "TEST_KEY", "TEST_VALUE"))))
+        .build();
+    validateOperationAuthorized(putMessage, inputStream, outputStream,
+        writeAllowed ? ClientProtocol.Response.ResponseAPICase.PUTRESPONSE
+            : ClientProtocol.Response.ResponseAPICase.ERRORRESPONSE);
+
+    ClientProtocol.Message removeMessage = ClientProtocol.Message.newBuilder()
+        .setRequest(ClientProtocol.Request.newBuilder()
+            .setRemoveRequest(RegionAPI.RemoveRequest.newBuilder().setRegionName(TEST_REGION)
+                .setKey(ProtobufUtilities.createEncodedValue(serializationService, "TEST_KEY"))))
+        .build();
+    validateOperationAuthorized(removeMessage, inputStream, outputStream,
+        writeAllowed ? ClientProtocol.Response.ResponseAPICase.REMOVERESPONSE
+            : ClientProtocol.Response.ResponseAPICase.ERRORRESPONSE);
+  }
+
+  private void validateOperationAuthorized(ClientProtocol.Message message, InputStream inputStream,
+      OutputStream outputStream, ClientProtocol.Response.ResponseAPICase expectedResponseType)
+      throws Exception {
+    protobufProtocolSerializer.serialize(message, outputStream);
+    ClientProtocol.Message response = protobufProtocolSerializer.deserialize(inputStream);
+    assertEquals(expectedResponseType, response.getResponse().getResponseAPICase());
+    if (expectedResponseType == ClientProtocol.Response.ResponseAPICase.ERRORRESPONSE) {
+      assertEquals(ProtocolErrorCode.AUTHORIZATION_FAILED.codeValue,
+          response.getResponse().getErrorResponse().getError().getErrorCode());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/a2b678aa/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessorTest.java
----------------------------------------------------------------------
diff --git a/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessorTest.java
b/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessorTest.java
index 16eb48b..668d280 100644
--- a/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessorTest.java
+++ b/geode-protobuf/src/test/java/org/apache/geode/protocol/protobuf/ProtobufStreamProcessorTest.java
@@ -27,6 +27,7 @@ import org.junit.experimental.categories.Category;
 
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.internal.cache.tier.sockets.MessageExecutionContext;
+import org.apache.geode.security.StreamAuthorizer;
 import org.apache.geode.test.junit.categories.UnitTest;
 
 @Category(UnitTest.class)


Mime
View raw message