geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jinmeil...@apache.org
Subject [2/6] incubator-geode git commit: GEODE-1570 - developer REST API should be secured
Date Mon, 10 Oct 2016 22:08:30 GMT
GEODE-1570 - developer REST API should be secured

* Merged with develop after org.apache package rename
* Moved classes to internal.
* this closes #251


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

Branch: refs/heads/develop
Commit: 5ed443d5bf8be3943fa76ce457f9592df5eb8317
Parents: a0acc3c
Author: Kevin Duling <kduling@pivotal.io>
Authored: Wed Sep 21 08:50:46 2016 -0700
Committer: Jinmei Liao <jiliao@pivotal.io>
Committed: Mon Oct 10 15:07:07 2016 -0700

----------------------------------------------------------------------
 .../internal/web/RestSecurityDUnitTest.java     | 247 +++++++++--
 .../web/RestSecurityEndpointsDUnitTest.java     | 422 +++++++++++++++++++
 .../src/main/webapp/WEB-INF/spring-security.xml |   2 +-
 geode-web-api/build.gradle                      |   6 +-
 .../web/controllers/AbstractBaseController.java |  54 ++-
 .../web/controllers/BaseControllerAdvice.java   |  78 +++-
 .../web/controllers/CommonCrudController.java   |  87 ++--
 .../controllers/FunctionAccessController.java   |  36 +-
 .../web/controllers/PdxBasedCrudController.java |  44 +-
 .../web/controllers/QueryAccessController.java  | 108 ++---
 .../web/security/GeodeAuthentication.java       |  37 ++
 .../security/GeodeAuthenticationProvider.java   |  56 +++
 .../internal/web/security/GeodeAuthority.java   |  47 +++
 .../web/security/RestSecurityConfiguration.java |  76 ++++
 .../src/main/webapp/WEB-INF/geode-servlet.xml   |  11 +-
 geode-web-api/src/main/webapp/WEB-INF/web.xml   |  20 +-
 gradle/dependency-versions.properties           |   4 +-
 17 files changed, 1116 insertions(+), 219 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityDUnitTest.java b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityDUnitTest.java
index df146a6..a9d90ed 100644
--- a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityDUnitTest.java
+++ b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityDUnitTest.java
@@ -22,75 +22,236 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
 
+import org.apache.geode.internal.AvailablePortHelper;
+import org.apache.geode.security.AbstractSecureServerDUnitTest;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.geode.test.junit.categories.SecurityTest;
 import org.apache.http.HttpEntity;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.AuthCache;
 import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.methods.HttpDelete;
 import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.junit.Test;
+import org.json.JSONTokener;
 import org.junit.experimental.categories.Category;
 
-import org.apache.geode.internal.AvailablePortHelper;
-import org.apache.geode.security.AbstractSecureServerDUnitTest;
-import org.apache.geode.test.junit.categories.DistributedTest;
-import org.apache.geode.test.junit.categories.SecurityTest;
 
-@Category({ DistributedTest.class, SecurityTest.class})
+@Category({ DistributedTest.class, SecurityTest.class })
 public class RestSecurityDUnitTest extends AbstractSecureServerDUnitTest {
-  private String endPoint = null;
-  public RestSecurityDUnitTest(){
+
+  public final static String PROTOCOL = "http";
+  public final static String HOSTNAME = "localhost";
+  public final static String CONTEXT = "/geode/v1";
+
+  private final String endPoint;
+  private final URL url;
+
+  public RestSecurityDUnitTest() throws MalformedURLException {
     int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
     this.jmxPort = ports[0];
     this.restPort = ports[1];
-    endPoint = "http://localhost:"+restPort+"/gemfire-api/v1";
+    endPoint = PROTOCOL + "://" + HOSTNAME + ":" + restPort + CONTEXT;
+    url = new URL(endPoint);
+  }
+
+  protected HttpResponse doHEAD(String query, String username, String password) throws MalformedURLException {
+    HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
+    HttpClientContext clientContext = HttpClientContext.create();
+    CredentialsProvider credsProvider = new BasicCredentialsProvider();
+    credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new UsernamePasswordCredentials(username, password));
+    CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
+    AuthCache authCache = new BasicAuthCache();
+    BasicScheme basicAuth = new BasicScheme();
+    authCache.put(targetHost, basicAuth);
+    clientContext.setCredentialsProvider(credsProvider);
+    clientContext.setAuthCache(authCache);
+
+    HttpHead httpHead = new HttpHead(CONTEXT + query);
+    try {
+      return httpclient.execute(targetHost, httpHead, clientContext);
+    } catch (ClientProtocolException e) {
+      e.printStackTrace();
+      fail("Rest HEAD should not have thrown ClientProtocolException!");
+    } catch (IOException e) {
+      e.printStackTrace();
+      fail("Rest HEAD Request should not have thrown IOException!");
+    }
+    return null;
+  }
+
+  protected HttpResponse doGet(String query, String username, String password) throws MalformedURLException {
+    HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
+    CloseableHttpClient httpclient = HttpClients.custom().build();
+    HttpClientContext clientContext = HttpClientContext.create();
+//    // if username or password are null or empty, do not put in authentication
+//    if (!(username == null
+//          || password == null
+//          || !username.isEmpty()
+//          || !password.isEmpty())) {
+      CredentialsProvider credsProvider = new BasicCredentialsProvider();
+      credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new UsernamePasswordCredentials(username, password));
+      httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
+      AuthCache authCache = new BasicAuthCache();
+      BasicScheme basicAuth = new BasicScheme();
+      authCache.put(targetHost, basicAuth);
+      clientContext.setCredentialsProvider(credsProvider);
+      clientContext.setAuthCache(authCache);
+//    }
+
+    HttpGet getRequest = new HttpGet(CONTEXT + query);
+    try {
+      return httpclient.execute(targetHost, getRequest, clientContext);
+    } catch (ClientProtocolException e) {
+      e.printStackTrace();
+      fail("Rest GET should not have thrown ClientProtocolException!");
+    } catch (IOException e) {
+      e.printStackTrace();
+      fail("Rest GET Request should not have thrown IOException!");
+    }
+    return null;
   }
-  @Test
-  public void test(){
-    client1.invoke(()->{
-      JSONArray response = doGet("/servers");
-      assertEquals(response.length(), 1);
-      assertEquals(response.get(0), "http://localhost:"+this.restPort);
-    });
+
+  protected HttpResponse doDelete(String query, String username, String password) throws MalformedURLException {
+    HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
+    CredentialsProvider credsProvider = new BasicCredentialsProvider();
+    credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new UsernamePasswordCredentials(username, password));
+    CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
+    AuthCache authCache = new BasicAuthCache();
+    BasicScheme basicAuth = new BasicScheme();
+    authCache.put(targetHost, basicAuth);
+
+    HttpClientContext clientContext = HttpClientContext.create();
+    clientContext.setCredentialsProvider(credsProvider);
+    clientContext.setAuthCache(authCache);
+
+    HttpDelete httpDelete = new HttpDelete(CONTEXT + query);
+    try {
+      return httpclient.execute(targetHost, httpDelete, clientContext);
+    } catch (ClientProtocolException e) {
+      e.printStackTrace();
+      fail("Rest DELETE Request should not have thrown ClientProtocolException!");
+    } catch (IOException e) {
+      e.printStackTrace();
+      fail("Rest DELETE Request should not have thrown IOException!");
+    }
+    return null;
   }
 
+  protected HttpResponse doPost(String query, String username, String password, String body) throws MalformedURLException {
+    HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
+    CredentialsProvider credsProvider = new BasicCredentialsProvider();
+    credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new UsernamePasswordCredentials(username, password));
+    CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
+    AuthCache authCache = new BasicAuthCache();
+    BasicScheme basicAuth = new BasicScheme();
+    authCache.put(targetHost, basicAuth);
 
-  private JSONArray doGet(String uri) {
-    HttpGet get = new HttpGet(endPoint + uri);
-    get.addHeader("Content-Type", "application/json");
-    get.addHeader("Accept", "application/json");
-    CloseableHttpClient httpclient = HttpClients.createDefault();
-    CloseableHttpResponse response;
+    HttpClientContext clientContext = HttpClientContext.create();
+    clientContext.setCredentialsProvider(credsProvider);
+    clientContext.setAuthCache(authCache);
 
+    HttpPost httpPost = new HttpPost(CONTEXT + query);
+    httpPost.addHeader("content-type", "application/json");
+    httpPost.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
     try {
-      response = httpclient.execute(get);
-      HttpEntity entity = response.getEntity();
-      InputStream content = entity.getContent();
-      BufferedReader reader = new BufferedReader(new InputStreamReader(
-        content));
-      String line;
-      StringBuffer str = new StringBuffer();
-      while ((line = reader.readLine()) != null) {
-        str.append(line);
-      }
-
-      //validate the satus code
-      assertEquals(response.getStatusLine().getStatusCode(), 200);
-      return new JSONArray(str.toString());
+      return httpclient.execute(targetHost, httpPost, clientContext);
     } catch (ClientProtocolException e) {
       e.printStackTrace();
-      fail(" Rest Request should not have thrown ClientProtocolException!");
+      fail("Rest POST Request should not have thrown ClientProtocolException!");
     } catch (IOException e) {
       e.printStackTrace();
-      fail(" Rest Request should not have thrown IOException!");
-    } catch (JSONException e) {
+      fail("Rest POST Request should not have thrown IOException!");
+    }
+    return null;
+  }
+  protected HttpResponse doPut(String query, String username, String password, String body) throws MalformedURLException {
+    HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
+    CredentialsProvider credsProvider = new BasicCredentialsProvider();
+    credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new UsernamePasswordCredentials(username, password));
+    CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
+    AuthCache authCache = new BasicAuthCache();
+    BasicScheme basicAuth = new BasicScheme();
+    authCache.put(targetHost, basicAuth);
+
+    HttpClientContext clientContext = HttpClientContext.create();
+    clientContext.setCredentialsProvider(credsProvider);
+    clientContext.setAuthCache(authCache);
+
+    HttpPut httpPut = new HttpPut(CONTEXT + query);
+    httpPut.addHeader("content-type", "application/json");
+    httpPut.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
+    try {
+      return httpclient.execute(targetHost, httpPut, clientContext);
+    } catch (ClientProtocolException e) {
       e.printStackTrace();
-      fail(" Rest Request should not have thrown  JSONException!");
+      fail("Rest PUT Request should not have thrown ClientProtocolException!");
+    } catch (IOException e) {
+      e.printStackTrace();
+      fail("Rest PUT Request should not have thrown IOException!");
     }
     return null;
   }
 
+  /**
+   * Check the HTTP status of the response and return if it's within the OK range
+   * @param response The HttpResponse message received from the server
+   *
+   * @return true if the status code is a 2XX-type code (200-299), otherwise false
+   */
+  protected boolean isOK(HttpResponse response) {
+    int returnCode = response.getStatusLine().getStatusCode();
+    return (returnCode < 300 && returnCode >= 200);
+  }
+
+  /**
+   * Check the HTTP status of the response and return true if a 401
+   * @param response The HttpResponse message received from the server
+   *
+   * @return true if the status code is 401, otherwise false
+   */
+  protected boolean isUnauthorized(HttpResponse response) {
+    int returnCode = response.getStatusLine().getStatusCode();
+    return returnCode == 401;
+  }
+
+  /**
+   * Retrieve the status code of the HttpResponse
+   * @param response The HttpResponse message received from the server
+   *
+   * @return a numeric value
+   */
+  protected int getCode(HttpResponse response) {
+    return response.getStatusLine().getStatusCode();
+  }
+
+  protected JSONTokener getResponseBody(HttpResponse response) throws IOException {
+    HttpEntity entity = response.getEntity();
+    InputStream content = entity.getContent();
+    BufferedReader reader = new BufferedReader(new InputStreamReader(
+      content));
+    String line;
+    StringBuilder str = new StringBuilder();
+    while ((line = reader.readLine()) != null) {
+      str.append(line);
+    }
+    return new JSONTokener(str.toString());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityEndpointsDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityEndpointsDUnitTest.java b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityEndpointsDUnitTest.java
new file mode 100644
index 0000000..149a905
--- /dev/null
+++ b/geode-assembly/src/test/java/org/apache/geode/rest/internal/web/RestSecurityEndpointsDUnitTest.java
@@ -0,0 +1,422 @@
+/*
+ * 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.rest.internal.web;
+
+import static org.junit.Assert.*;
+
+import java.net.MalformedURLException;
+
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.geode.test.junit.categories.SecurityTest;
+import org.apache.http.HttpResponse;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("serial")
+@Category({ DistributedTest.class, SecurityTest.class })
+public class RestSecurityEndpointsDUnitTest extends RestSecurityDUnitTest {
+
+  Logger logger = LoggerFactory.getLogger(RestSecurityEndpointsDUnitTest.class);
+
+  public RestSecurityEndpointsDUnitTest() throws MalformedURLException {
+    super();
+  }
+
+  @Test
+  public void testFunctions() {
+    client1.invoke(() -> {
+      String json = "{\"@type\":\"double\",\"@value\":210}";
+
+      HttpResponse response = doGet("/functions", "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+      response = doGet("/functions", "stranger", "1234567");
+      assertEquals(403, getCode(response));
+      response = doGet("/functions", "dataReader", "1234567");
+      assertTrue(isOK(response));
+
+      response = doPost("/functions/AddFreeItemsToOrder", "unknown-user", "1234567", json);
+      assertEquals(401, getCode(response));
+      response = doPost("/functions/AddFreeItemsToOrder", "dataReader", "1234567", json);
+      assertEquals(403, getCode(response));
+      response = doPost("/functions/AddFreeItemsToOrder?onRegion=" + REGION_NAME, "dataWriter", "1234567", json);
+      // because we're only testing the security of the endpoint, not the endpoint functionality, a 500 is acceptable
+      assertEquals(500, getCode(response));
+    });
+  }
+
+  @Test
+  public void testQueries() {
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/queries", "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+      response = doGet("/queries", "stranger", "1234567");
+      assertEquals(403, getCode(response));
+      response = doGet("/queries", "dataReader", "1234567");
+      assertEquals(200, getCode(response));
+    });
+  }
+
+  @Test
+  public void testAdhocQuery() {
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/queries/adhoc?q=", "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+      response = doGet("/queries/adhoc?q=", "stranger", "1234567");
+      assertEquals(403, getCode(response));
+      response = doGet("/queries/adhoc?q=", "dataReader", "1234567");
+      // because we're only testing the security of the endpoint, not the endpoint functionality, a 500 is acceptable
+      assertEquals(500, getCode(response));
+    });
+  }
+
+  @Test
+  public void testPostQuery() {
+    client1.invoke(() -> {
+      HttpResponse response = doPost("/queries?id=0&q=", "unknown-user", "1234567", "");
+      assertEquals(401, getCode(response));
+      response = doPost("/queries?id=0&q=", "stranger", "1234567", "");
+      assertEquals(403, getCode(response));
+      response = doPost("/queries?id=0&q=", "dataWriter", "1234567", "");
+      // because we're only testing the security of the endpoint, not the endpoint functionality, a 500 is acceptable
+      assertEquals(500, getCode(response));
+    });
+  }
+
+  @Test
+  public void testPostQuery2() {
+    client1.invoke(() -> {
+      HttpResponse response = doPost("/queries/id", "unknown-user", "1234567", "{\"id\" : \"foo\"}");
+      assertEquals(401, getCode(response));
+      response = doPost("/queries/id", "stranger", "1234567", "{\"id\" : \"foo\"}");
+      assertEquals(403, getCode(response));
+      response = doPost("/queries/id", "dataWriter", "1234567", "{\"id\" : \"foo\"}");
+      // because we're only testing the security of the endpoint, not the endpoint functionality, a 500 is acceptable
+      assertEquals(500, getCode(response));
+    });
+  }
+
+  @Test
+  public void testPutQuery() {
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/queries/id", "unknown-user", "1234567", "{\"id\" : \"foo\"}");
+      assertEquals(401, getCode(response));
+      response = doPut("/queries/id", "stranger", "1234567", "{\"id\" : \"foo\"}");
+      assertEquals(403, getCode(response));
+      response = doPut("/queries/id", "dataWriter", "1234567", "{\"id\" : \"foo\"}");
+      // We should get a 404 because we're trying to update a query that doesn't exist
+      assertEquals(404, getCode(response));
+    });
+  }
+
+  @Test
+  public void testDeleteQuery() {
+    client1.invoke(() -> {
+      HttpResponse response = doDelete("/queries/id", "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+      response = doDelete("/queries/id", "stranger", "1234567");
+      assertEquals(403, getCode(response));
+      response = doDelete("/queries/id", "dataWriter", "1234567");
+      // We should get a 404 because we're trying to delete a query that doesn't exist
+      assertEquals(404, getCode(response));
+    });
+  }
+
+  @Test
+  public void testServers() {
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/servers", "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+      response = doGet("/servers", "stranger", "1234567");
+      assertEquals(403, getCode(response));
+      response = doGet("/servers", "super-user", "1234567");
+      assertTrue(isOK(response));
+    });
+  }
+
+  /**
+   * This test should always return an OK, whether the user is known or unknown.  A phishing script should not be
+   * able to determine whether a user/password combination is good
+   */
+  @Test
+  public void testPing() {
+    client1.invoke(() -> {
+      HttpResponse response = doHEAD("/ping", "stranger", "1234567");
+      assertTrue(isOK(response));
+      response = doGet("/ping", "stranger", "1234567");
+      assertTrue(isOK(response));
+
+      response = doHEAD("/ping", "super-user", "1234567");
+      assertTrue(isOK(response));
+      response = doGet("/ping", "super-user", "1234567");
+      assertTrue(isOK(response));
+
+      // TODO - invalid username/password should still respond, but doesn't
+      //      response = doHEAD("/ping", "unknown-user", "badpassword");
+      //      assertTrue(isOK(response));
+      //      response = doGet("/ping", "unknown-user", "badpassword");
+      //      assertTrue(isOK(response));
+
+      // TODO - credentials are currently required and shouldn't be for this endpoint
+      //      response = doHEAD("/ping", null, null);
+      //      assertTrue(isOK(response));
+      //      response = doGet("/ping", null, null);
+      //      assertTrue(isOK(response));
+    });
+  }
+
+  /**
+   * Test permissions on retrieving a list of regions.
+   */
+  @Test
+  public void getRegions() {
+    client1.invoke(() -> {
+      HttpResponse response = doGet("", "dataReader", "1234567");
+      assertEquals("A '200 - OK' was expected", 200, getCode(response));
+
+      assertTrue(isOK(response));
+      JSONObject jsonObject = new JSONObject(getResponseBody(response));
+      JSONArray regions = jsonObject.getJSONArray("regions");
+      assertNotNull(regions);
+      assertTrue(regions.length() > 0);
+      JSONObject region = regions.getJSONObject(0);
+      assertEquals("AuthRegion", region.get("name"));
+      assertEquals("REPLICATE", region.get("type"));
+    });
+
+    // List regions with an unknown user - 401
+    client1.invoke(() -> {
+      HttpResponse response = doGet("", "unknown-user", "badpassword");
+      assertEquals(401, getCode(response));
+    });
+
+    // list regions with insufficent rights - 403
+    client1.invoke(() -> {
+      HttpResponse response = doGet("", "authRegionReader", "1234567");
+      assertEquals(403, getCode(response));
+    });
+  }
+
+  /**
+   * Test permissions on getting a region
+   */
+  @Test
+  public void getRegion() {
+    // Test an unknown user - 401 error
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/" + REGION_NAME, "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+    });
+
+    // Test a user with insufficient rights - 403
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/" + REGION_NAME, "stranger", "1234567");
+      assertEquals(403, getCode(response));
+    });
+
+    // Test an authorized user - 200
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/" + REGION_NAME, "super-user", "1234567");
+      assertTrue(isOK(response));
+    });
+  }
+
+  /**
+   * Test permissions on HEAD region
+   */
+  @Test
+  public void headRegion() {
+    // Test an unknown user - 401 error
+    client1.invoke(() -> {
+      HttpResponse response = doHEAD("/" + REGION_NAME, "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+    });
+
+    // Test a user with insufficient rights - 403
+    client1.invoke(() -> {
+      HttpResponse response = doHEAD("/" + REGION_NAME, "stranger", "1234567");
+      assertEquals(403, getCode(response));
+    });
+
+    // Test an authorized user - 200
+    client1.invoke(() -> {
+      HttpResponse response = doHEAD("/" + REGION_NAME, "super-user", "1234567");
+      assertTrue(isOK(response));
+    });
+  }
+
+  /**
+   * Test permissions on deleting a region
+   */
+  @Test
+  public void deleteRegion() {
+    // Test an unknown user - 401 error
+    client1.invoke(() -> {
+      HttpResponse response = doDelete("/" + REGION_NAME, "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+    });
+
+    // Test a user with insufficient rights - 403
+    client1.invoke(() -> {
+      HttpResponse response = doDelete("/" + REGION_NAME, "dataReader", "1234567");
+      assertEquals(403, getCode(response));
+    });
+
+    // Test an authorized user - 200
+    client1.invoke(() -> {
+      HttpResponse response = doDelete("/" + REGION_NAME, "super-user", "1234567");
+      assertTrue(isOK(response));
+    });
+  }
+
+  /**
+   * Test permissions on getting a region's keys
+   */
+  @Test
+  public void getRegionKeys() {
+    // Test an authorized user
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/" + REGION_NAME + "/keys", "super-user", "1234567");
+      assertTrue(isOK(response));
+    });
+    // Test an unauthorized user
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/" + REGION_NAME + "/keys", "dataWriter", "1234567");
+      assertEquals(403, getCode(response));
+    });
+  }
+
+  /**
+   * Test permissions on retrieving a key from a region
+   */
+  @Test
+  public void getRegionKey() {
+    // Test an authorized user
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/" + REGION_NAME + "/key1", "key1User", "1234567");
+      assertTrue(isOK(response));
+    });
+    // Test an unauthorized user
+    client1.invoke(() -> {
+      HttpResponse response = doGet("/" + REGION_NAME + "/key1", "dataWriter", "1234567");
+      assertEquals(403, getCode(response));
+    });
+  }
+
+  /**
+   * Test permissions on deleting a region's key(s)
+   */
+  @Test
+  public void deleteRegionKey() {
+    // Test an unknown user - 401 error
+    client1.invoke(() -> {
+      HttpResponse response = doDelete("/" + REGION_NAME + "/key1", "unknown-user", "1234567");
+      assertEquals(401, getCode(response));
+    });
+
+    // Test a user with insufficient rights - 403
+    client1.invoke(() -> {
+      HttpResponse response = doDelete("/" + REGION_NAME + "/key1", "dataReader", "1234567");
+      assertEquals(403, getCode(response));
+    });
+
+    // Test an authorized user - 200
+    client1.invoke(() -> {
+      HttpResponse response = doDelete("/" + REGION_NAME + "/key1", "key1User", "1234567");
+      assertTrue(isOK(response));
+    });
+  }
+
+  /**
+   * Test permissions on deleting a region's key(s)
+   */
+  @Test
+  public void postRegionKey() {
+    // Test an unknown user - 401 error
+    client1.invoke(() -> {
+      HttpResponse response = doPost("/" + REGION_NAME + "?key9", "unknown", "1234567", "{ \"key9\" : \"foo\" }");
+      assertEquals(401, getCode(response));
+    });
+
+    // Test a user with insufficient rights - 403
+    client1.invoke(() -> {
+      HttpResponse response = doPost("/" + REGION_NAME + "?key9", "dataReader", "1234567", "{ \"key9\" : \"foo\" }");
+      assertEquals(403, getCode(response));
+    });
+
+    // Test an authorized user - 200
+    client1.invoke(() -> {
+      HttpResponse response = doPost("/" + REGION_NAME + "?key9", "dataWriter", "1234567", "{ \"key9\" : \"foo\" }");
+      assertEquals(201, getCode(response));
+      assertTrue(isOK(response));
+    });
+  }
+
+  /**
+   * Test permissions on deleting a region's key(s)
+   */
+  @Test
+  public void putRegionKey() {
+
+    String json = "{\"@type\":\"com.gemstone.gemfire.web.rest.domain.Order\",\"purchaseOrderNo\":1121,\"customerId\":1012,\"description\":\"Order for  XYZ Corp\",\"orderDate\":\"02/10/2014\",\"deliveryDate\":\"02/20/2014\",\"contact\":\"Jelly Bean\",\"email\":\"jelly.bean@example.com\",\"phone\":\"01-2048096\",\"items\":[{\"itemNo\":1,\"description\":\"Product-100\",\"quantity\":12,\"unitPrice\":5,\"totalPrice\":60}],\"totalPrice\":225}";
+    String casJSON = "{\"@old\":{\"@type\":\"com.gemstone.gemfire.web.rest.domain.Order\",\"purchaseOrderNo\":1121,\"customerId\":1012,\"description\":\"Order for  XYZ Corp\",\"orderDate\":\"02/10/2014\",\"deliveryDate\":\"02/20/2014\",\"contact\":\"Jelly Bean\",\"email\":\"jelly.bean@example.com\",\"phone\":\"01-2048096\",\"items\":[{\"itemNo\":1,\"description\":\"Product-100\",\"quantity\":12,\"unitPrice\":5,\"totalPrice\":60}],\"totalPrice\":225},\"@new \":{\"@type\":\"com.gemstone.gemfire.web.rest.domain.Order\",\"purchaseOrderNo\":1121,\"customerId\":1013,\"description\":\"Order for  New Corp\",\"orderDate\":\"02/10/2014\",\"deliveryDate\":\"02/25/2014\",\"contact\":\"Vanilla Bean\",\"email\":\"vanillabean@example.com\",\"phone\":\"01-2048096\",\"items\":[{\"itemNo\":12345,\"description\":\"part 123\",\"quantity\":12,\"unitPrice\":29.99,\"totalPrice\":149.95}],\"totalPrice\":149.95}}";
+    // Test an unknown user - 401 error
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/" + REGION_NAME + "/key1?op=PUT", "unknown-user", "1234567", "{ \"key9\" : \"foo\" }");
+      assertEquals(401, getCode(response));
+    });
+
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/" + REGION_NAME + "/key1?op=CAS", "unknown-user", "1234567", "{ \"key9\" : \"foo\" }");
+      assertEquals(401, getCode(response));
+    });
+
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/" + REGION_NAME + "/key1?op=REPLACE", "unknown-user", "1234567", "{ \"@old\" : \"value1\", \"@new\" : \"CASvalue\" }");
+      assertEquals(401, getCode(response));
+    });
+
+    // Test a user with insufficient rights - 403
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/" + REGION_NAME + "/key1?op=PUT", "dataReader", "1234567", "{ \"key1\" : \"foo\" }");
+      assertEquals(403, getCode(response));
+    });
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/" + REGION_NAME + "/key1?op=REPLACE", "dataReader", "1234567", "{ \"key1\" : \"foo\" }");
+      assertEquals(403, getCode(response));
+    });
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/" + REGION_NAME + "/key1?op=CAS", "dataReader", "1234567", casJSON);
+      assertEquals(403, getCode(response));
+    });
+
+    // Test an authorized user - 200
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/" + REGION_NAME + "/key1?op=PUT", "key1User", "1234567", "{ \"key1\" : \"foo\" }");
+      assertEquals(200, getCode(response));
+      assertTrue(isOK(response));
+    });
+    client1.invoke(() -> {
+      HttpResponse response = doPut("/" + REGION_NAME + "/key1?op=REPLACE", "key1User", "1234567", json);
+      assertEquals(200, getCode(response));
+      assertTrue(isOK(response));
+    });
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
----------------------------------------------------------------------
diff --git a/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml b/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
index 3756df7..924dd50 100644
--- a/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
+++ b/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
@@ -22,7 +22,7 @@
 	xsi:schemaLocation="http://www.springframework.org/schema/beans
 	http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 	http://www.springframework.org/schema/security
-	http://www.springframework.org/schema/security/spring-security-3.1.xsd
+	http://www.springframework.org/schema/security/spring-security-3.2.xsd
 	http://www.springframework.org/schema/context
 	http://www.springframework.org/schema/context/spring-context-3.2.xsd">
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-web-api/build.gradle
----------------------------------------------------------------------
diff --git a/geode-web-api/build.gradle b/geode-web-api/build.gradle
index 9e93bb9..3ea652b 100755
--- a/geode-web-api/build.gradle
+++ b/geode-web-api/build.gradle
@@ -29,7 +29,7 @@ dependencies {
   compile 'com.fasterxml.jackson.core:jackson-databind:' + project.'jackson.version'
   compile 'com.fasterxml.jackson.module:jackson-module-scala_2.10:' + project.'jackson-module-scala_2.10.version'
   compile 'com.google.guava:guava:' + project.'guava.version'
-  compile ('com.mangofactory:swagger-springmvc:' + project.'swagger-springmvc.version') { 
+  compile ('com.mangofactory:swagger-springmvc:' + project.'swagger-springmvc.version') {
     exclude module: 'aopalliance'
     exclude module: 'asm'
     exclude module: 'cglib'
@@ -53,6 +53,10 @@ dependencies {
   compile 'org.json4s:json4s-ast_2.10:' + project.'json4s.version'
   compile 'org.scala-lang:scala-library:' + project.'scala.version'
   compile 'org.scala-lang:scala-reflect:' + project.'scala.version'
+  compile 'org.springframework:spring-beans:' + project.'springframework.version'
+  compile 'org.springframework.security:spring-security-core:' + project.'spring-security.version'
+  compile 'org.springframework.security:spring-security-web:' + project.'spring-security.version'
+  compile 'org.springframework.security:spring-security-config:' + project.'spring-security.version'
   compile ('org.springframework.hateoas:spring-hateoas:' + project.'spring-hateoas.version') {
     exclude module: 'aopalliance'
     exclude module: 'commons-logging'

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java
----------------------------------------------------------------------
diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java
index e94998b..ee5d714 100644
--- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java
+++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/AbstractBaseController.java
@@ -35,17 +35,6 @@ import java.util.concurrent.atomic.AtomicLong;
 
 import javax.annotation.PostConstruct;
 
-import org.apache.logging.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
-import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
-
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonMappingException;
@@ -60,13 +49,13 @@ import org.apache.geode.cache.Region;
 import org.apache.geode.cache.TimeoutException;
 import org.apache.geode.cache.query.QueryService;
 import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.LeaseExpiredException;
 import org.apache.geode.distributed.internal.DistributionManager;
-import org.apache.geode.distributed.internal.InternalDistributedSystem;
 import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
-import org.apache.geode.i18n.LogWriterI18n;
 import org.apache.geode.internal.cache.GemFireCacheImpl;
-import org.apache.geode.internal.i18n.LocalizedStrings;
 import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.internal.security.IntegratedSecurityService;
+import org.apache.geode.internal.security.SecurityService;
 import org.apache.geode.pdx.JSONFormatter;
 import org.apache.geode.pdx.JSONFormatterException;
 import org.apache.geode.pdx.PdxInstance;
@@ -82,10 +71,21 @@ import org.apache.geode.rest.internal.web.util.IdentifiableUtils;
 import org.apache.geode.rest.internal.web.util.JSONUtils;
 import org.apache.geode.rest.internal.web.util.NumberUtils;
 import org.apache.geode.rest.internal.web.util.ValidationUtils;
+import org.apache.logging.log4j.Logger;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.json.JSONTokener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
 
 /**
  * AbstractBaseController class contains common functionalities required for other controllers. 
@@ -104,6 +104,7 @@ public abstract class AbstractBaseController {
   protected static final String UTF_8 = "UTF-8";
   protected static final String DEFAULT_ENCODING = UTF_8;
   private static final AtomicLong ID_SEQUENCE = new AtomicLong(0l);
+  protected SecurityService securityService = IntegratedSecurityService.getSecurityService();
   
   //private Cache cache = GemFireCacheImpl.getExisting(null);
   
@@ -199,7 +200,7 @@ public abstract class AbstractBaseController {
       
       final HttpHeaders headers = new HttpHeaders();
       headers.setLocation(toUri("queries", queryId));    
-      return new ResponseEntity<>(queryResultAsJson, headers, HttpStatus.OK);
+      return new ResponseEntity<String>(queryResultAsJson, headers, HttpStatus.OK);
     }else {
       throw new GemfireRestException("Server has encountered error while generating query result into restful format(JSON)!");
     }
@@ -252,7 +253,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException(String.format("Resource (%1$s) configuration does not allow null keys or values!", regionNamePath), npe);
     }catch(IllegalArgumentException iae){
       throw new GemfireRestException(String.format("Resource (%1$s) configuration prevents specified data from being stored in it!", regionNamePath), iae);
-    }catch(org.apache.geode.distributed.LeaseExpiredException lee){
+    }catch(LeaseExpiredException lee){
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     }catch(TimeoutException toe){
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", toe);
@@ -278,7 +279,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException(String.format("Resource (%1$s) configuration does not allow null keys or values!", regionNamePath), npe);
     }catch(IllegalArgumentException iae){
       throw new GemfireRestException(String.format("Resource (%1$s) configuration prevents specified data from being stored in it!", regionNamePath), iae);
-    }catch(org.apache.geode.distributed.LeaseExpiredException lee){
+    }catch(LeaseExpiredException lee){
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     }catch(TimeoutException toe){
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", toe);
@@ -305,7 +306,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException(String.format("Resource (%1$s) configuration does not allow null keys or values!", regionNamePath), npe);
     }catch(IllegalArgumentException iae){
       throw new GemfireRestException(String.format("Resource (%1$s) configuration prevents specified data from being stored in it!", regionNamePath), iae);
-    }catch(org.apache.geode.distributed.LeaseExpiredException lee){
+    }catch(LeaseExpiredException lee){
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     }catch(TimeoutException toe){
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", toe);
@@ -325,7 +326,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException(String.format("Resource (%1$s) configuration does not allow null keys or values!", regionNamePath), npe);
     } catch (ClassCastException cce) {
       throw new GemfireRestException(String.format("Resource (%1$s) configuration does not allow to store specified key or value type in this region!", regionNamePath), cce);
-    } catch (org.apache.geode.distributed.LeaseExpiredException lee) {
+    } catch (LeaseExpiredException lee) {
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     } catch (TimeoutException toe) {
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", toe);
@@ -368,7 +369,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException("NULL query ID or query string is not supported!", npe);
     } catch(IllegalArgumentException iae) {
       throw new GemfireRestException("Server has not allowed to perform the requested operation!", iae);
-    } catch(org.apache.geode.distributed.LeaseExpiredException lee) {
+    } catch(LeaseExpiredException lee) {
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     } catch(TimeoutException te) {
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", te);
@@ -382,7 +383,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException("NULL query ID or query string is not supported!", npe);
     } catch (ClassCastException cce) {
       throw new GemfireRestException("specified queryId or query string is not supported!", cce);
-    } catch (org.apache.geode.distributed.LeaseExpiredException lee) {
+    } catch (LeaseExpiredException lee) {
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     } catch (TimeoutException toe) {
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", toe);
@@ -403,7 +404,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException("NULL query ID or query string is not supported!", npe);
     } catch(IllegalArgumentException iae){
       throw new GemfireRestException("Configuration does not allow to perform the requested operation!", iae);
-    } catch(org.apache.geode.distributed.LeaseExpiredException lee){
+    } catch(LeaseExpiredException lee){
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     } catch(TimeoutException toe){
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", toe);
@@ -451,7 +452,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException(String.format("Resource (%1$s) configuration does not allow null keys or values!", regionNamePath), npe);
     }catch(IllegalArgumentException iae){
       throw new GemfireRestException(String.format("Resource (%1$s) configuration prevents specified data from being stored in it!", regionNamePath), iae);
-    }catch(org.apache.geode.distributed.LeaseExpiredException lee){
+    }catch(LeaseExpiredException lee){
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     }catch(TimeoutException toe){
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", toe);
@@ -645,10 +646,7 @@ public abstract class AbstractBaseController {
   protected String convertErrorAsJson(Throwable t) {
     StringWriter writer = new StringWriter();
     t.printStackTrace(new PrintWriter(writer));
-    String returnString = writer.toString();
-    returnString = returnString.replace("\n"," ");
-    returnString = returnString.replace("\t"," ");
-    return String.format("{\"message\" : \"%1$s\", \"stackTrace\" : \"%2$s\"}", t.getMessage(), returnString);
+    return String.format("{\"message\" : \"%1$s\", \"stackTrace\" : \"%2$s\"}", t.getMessage(), writer.toString());
   }
 
   protected Map<?,?> convertJsonToMap(final String jsonString) {
@@ -794,7 +792,7 @@ public abstract class AbstractBaseController {
       throw new GemfireRestException(String.format("Resource (%1$s) configuration does not allow null keys!", regionNamePath), npe);
     } catch(IllegalArgumentException iae) {
       throw new GemfireRestException(String.format("Resource (%1$s) configuration does not allow requested operation on specified key!", regionNamePath), iae);
-    } catch(org.apache.geode.distributed.LeaseExpiredException lee) {
+    } catch(LeaseExpiredException lee) {
       throw new GemfireRestException("Server has encountered error while processing this request!", lee);
     } catch(TimeoutException te) {
       throw new GemfireRestException("Server has encountered timeout error while processing this request!", te);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/BaseControllerAdvice.java
----------------------------------------------------------------------
diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/BaseControllerAdvice.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/BaseControllerAdvice.java
index a4f58b9..54dd9e5 100644
--- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/BaseControllerAdvice.java
+++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/BaseControllerAdvice.java
@@ -20,20 +20,24 @@ package org.apache.geode.rest.internal.web.controllers;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.rest.internal.web.exception.DataTypeNotSupportedException;
+import org.apache.geode.rest.internal.web.exception.GemfireRestException;
+import org.apache.geode.rest.internal.web.exception.MalformedJsonException;
+import org.apache.geode.rest.internal.web.exception.RegionNotFoundException;
+import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException;
+import org.apache.geode.security.AuthenticationFailedException;
+import org.apache.geode.security.NotAuthorizedException;
 import org.apache.logging.log4j.Logger;
+import org.apache.shiro.authc.AuthenticationException;
 import org.springframework.http.HttpStatus;
+import org.springframework.security.access.AccessDeniedException;
 import org.springframework.web.HttpRequestMethodNotSupportedException;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.ResponseStatus;
 
-import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.rest.internal.web.exception.DataTypeNotSupportedException;
-import org.apache.geode.rest.internal.web.exception.GemfireRestException;
-import org.apache.geode.rest.internal.web.exception.MalformedJsonException;
-import org.apache.geode.rest.internal.web.exception.RegionNotFoundException;
-import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException;
 
 /**
  * The CrudControllerAdvice class handles exception thrown while serving the REST request
@@ -43,7 +47,7 @@ import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException;
 
 @ControllerAdvice
 @SuppressWarnings("unused")
-public class BaseControllerAdvice extends AbstractBaseController{
+public class BaseControllerAdvice extends AbstractBaseController {
 
   private static final Logger logger = LogService.getLogger();
   
@@ -121,6 +125,58 @@ public class BaseControllerAdvice extends AbstractBaseController{
   }
  
   /**
+   * Handles an AuthenticationFailedException thrown by a REST API web service endpoint, HTTP request handler method.
+   * <p/>
+   * @param cause the Exception causing the error.
+   * @return a ResponseEntity with an appropriate HTTP status code (403 - Forbidden)
+   */
+  @ExceptionHandler(AuthenticationFailedException.class)
+  @ResponseBody
+  @ResponseStatus(HttpStatus.UNAUTHORIZED)
+  public String handleException(final AuthenticationFailedException cause) {
+    return convertErrorAsJson(cause.getMessage());
+  }
+
+  /**
+   * Handles an AuthenticationException thrown by a REST API web service endpoint, HTTP request handler method.
+   * <p/>
+   * @param cause the Exception causing the error.
+   * @return a ResponseEntity with an appropriate HTTP status code (403 - Forbidden)
+   */
+  @ExceptionHandler(AuthenticationException.class)
+  @ResponseBody
+  @ResponseStatus(HttpStatus.UNAUTHORIZED)
+  public String handleException(final AuthenticationException cause) {
+    return convertErrorAsJson(cause.getMessage());
+  }
+
+  /**
+   * Handles an AccessDenied Exception thrown by a REST API web service endpoint, HTTP request handler method.
+   * <p/>
+   * @param cause the Exception causing the error.
+   * @return a ResponseEntity with an appropriate HTTP status code (403 - Forbidden)
+   */
+  @ExceptionHandler(AccessDeniedException.class)
+  @ResponseBody
+  @ResponseStatus(HttpStatus.FORBIDDEN)
+  public String handleException(final AccessDeniedException cause) {
+    return convertErrorAsJson(cause.getMessage());
+  }
+
+  /**
+   * Handles an NotAuthorized Exception thrown by a GeodeSecurityUtil.
+   * <p/>
+   * @param cause the Exception causing the error.
+   * @return a ResponseEntity with an appropriate HTTP status code (403 - Forbidden)
+   */
+  @ExceptionHandler(NotAuthorizedException.class)
+  @ResponseBody
+  @ResponseStatus(HttpStatus.FORBIDDEN)
+  public String handleException(final NotAuthorizedException cause) {
+    return convertErrorAsJson(cause.getMessage());
+  }
+
+  /**
    * Handles any Exception thrown by a REST API web service endpoint, HTTP request handler method.
    * <p/>
    * @param cause the Exception causing the error.
@@ -134,13 +190,13 @@ public class BaseControllerAdvice extends AbstractBaseController{
     final StringWriter stackTraceWriter = new StringWriter();
     cause.printStackTrace(new PrintWriter(stackTraceWriter));
     final String stackTrace = stackTraceWriter.toString();
-    
+
     if(logger.isDebugEnabled()){
-      logger.debug(stackTrace);  
+      logger.debug(stackTrace);
     }
-    
+
     return convertErrorAsJson(cause.getMessage());
   }
-  
+
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java
----------------------------------------------------------------------
diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java
index b312884..232f034 100644
--- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java
+++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/CommonCrudController.java
@@ -21,15 +21,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
-import org.apache.logging.log4j.Logger;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
 import org.apache.geode.cache.LowMemoryException;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.execute.Execution;
@@ -38,14 +32,20 @@ import org.apache.geode.cache.execute.FunctionService;
 import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.internal.cache.GemFireCacheImpl;
 import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.internal.util.ArrayUtils;
 import org.apache.geode.rest.internal.web.controllers.support.RestServersResultCollector;
 import org.apache.geode.rest.internal.web.exception.GemfireRestException;
+import org.apache.geode.rest.internal.web.util.ArrayUtils;
 import org.apache.geode.rest.internal.web.util.JSONUtils;
+import org.apache.logging.log4j.Logger;
 import org.json.JSONException;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
 
 /**
  * The CommonCrudController serves REST Requests related to listing regions, 
@@ -71,19 +71,20 @@ public abstract class CommonCrudController extends AbstractBaseController {
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK." ),
-    @ApiResponse( code = 500, message = "GemFire throws an error or exception." )   
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
+    @ApiResponse( code = 500, message = "GemFire throws an error or exception." )
   } )
   public ResponseEntity<?> regions() {
-    
+    securityService.authorizeDataRead();
     if(logger.isDebugEnabled()){
       logger.debug("Listing all resources (Regions) in GemFire...");
     }
-    
+    final HttpHeaders headers = new HttpHeaders();
+    headers.setLocation(toUri());
     final Set<Region<?, ?>> regions = getCache().rootRegions();
     String listRegionsAsJson =  JSONUtils.formulateJsonForListRegions(regions, "regions");
-    final HttpHeaders headers = new HttpHeaders();  
-    headers.setLocation(toUri());
-    return new ResponseEntity<String>(listRegionsAsJson, headers, HttpStatus.OK);
+    return new ResponseEntity<>(listRegionsAsJson, headers, HttpStatus.OK);
   }
   
   /**
@@ -91,7 +92,7 @@ public abstract class CommonCrudController extends AbstractBaseController {
    * @param region gemfire region
    * @return JSON document containing result
    */
-  @RequestMapping(method = RequestMethod.GET, value = "/{region}/keys", 
+  @RequestMapping(method = RequestMethod.GET, value = "/{region}/keys",
                   produces = { MediaType.APPLICATION_JSON_VALUE } )
   @ApiOperation(
     value = "list all keys",
@@ -100,11 +101,13 @@ public abstract class CommonCrudController extends AbstractBaseController {
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK" ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "Region does not exist" ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception" )   
   } )
-  public ResponseEntity<?> keys(@PathVariable("region") String region){ 
-    
+  public ResponseEntity<?> keys(@PathVariable("region") String region){
+    securityService.authorizeRegionRead(region);
     if(logger.isDebugEnabled()){
       logger.debug("Reading all Keys in Region ({})...", region);
     }
@@ -116,7 +119,7 @@ public abstract class CommonCrudController extends AbstractBaseController {
     String listKeysAsJson =  JSONUtils.formulateJsonForListKeys(keys, "keys");
     final HttpHeaders headers = new HttpHeaders();  
     headers.setLocation(toUri(region, "keys"));
-    return new ResponseEntity<String>(listKeysAsJson, headers, HttpStatus.OK);
+    return new ResponseEntity<>(listKeysAsJson, headers, HttpStatus.OK);
   }
   
   /**
@@ -134,11 +137,15 @@ public abstract class CommonCrudController extends AbstractBaseController {
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK" ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "Region or key(s) does not exist" ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception" )      
   } )
   public ResponseEntity<?> delete(@PathVariable("region") String region,
-                                  @PathVariable("keys") final String[] keys){     
+                                  @PathVariable("keys") final String[] keys){
+    for (String key : keys)
+      securityService.authorizeRegionWrite(region, key);
     if(logger.isDebugEnabled()){
       logger.debug("Delete data for key {} on region {}", ArrayUtils.toString((Object[])keys), region);
     }
@@ -146,7 +153,7 @@ public abstract class CommonCrudController extends AbstractBaseController {
     region = decode(region);
     
     deleteValues(region, (Object[])keys);
-    return new ResponseEntity<Object>(HttpStatus.OK);
+    return new ResponseEntity<>(HttpStatus.OK);
   }
 
   /**
@@ -162,21 +169,27 @@ public abstract class CommonCrudController extends AbstractBaseController {
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK" ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "Region does not exist" ),
     @ApiResponse( code = 500, message = "if GemFire throws an error or exception" )   
   } )
   public ResponseEntity<?> delete(@PathVariable("region") String region) {
-    
+    securityService.authorizeRegionWrite(region);
     if(logger.isDebugEnabled()){
       logger.debug("Deleting all data in Region ({})...", region);
     }
-    
+
     region = decode(region);
     
     deleteValues(region);
-    return new ResponseEntity<Object>(HttpStatus.OK);
+    return new ResponseEntity<>(HttpStatus.OK);
   }
-  
+
+  /**
+   * Ping is not secured so that it may not be used to determine a valid username/password
+   * @return
+   */
   @RequestMapping(method = { RequestMethod.GET, RequestMethod.HEAD }, value = "/ping")
   @ApiOperation(
     value = "Check Rest service status ",
@@ -188,7 +201,7 @@ public abstract class CommonCrudController extends AbstractBaseController {
     @ApiResponse( code = 500, message = "if GemFire throws an error or exception" )   
   } )
   public ResponseEntity<?> ping() {
-    return new ResponseEntity<Object>(HttpStatus.OK);
+    return new ResponseEntity<>(HttpStatus.OK);
   }
   
   @RequestMapping(method = { RequestMethod.GET }, value = "/servers")
@@ -199,15 +212,17 @@ public abstract class CommonCrudController extends AbstractBaseController {
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK" ),
-    @ApiResponse( code = 500, message = "if GemFire throws an error or exception" )   
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
+    @ApiResponse( code = 500, message = "if GemFire throws an error or exception" )
   } )
   public ResponseEntity<?> servers() {
-    Execution function = null;
-      
+    securityService.authorizeClusterRead();
     if(logger.isDebugEnabled()){
       logger.debug("Executing function to get REST enabled gemfire nodes in the DS!");
     }
-      
+
+    Execution function;
     try {
       function = FunctionService.onMembers(getAllMembersInDS());
     } catch(FunctionException fe) {
@@ -223,7 +238,7 @@ public abstract class CommonCrudController extends AbstractBaseController {
         headers.setLocation(toUri("servers"));
         try {    
           String functionResultAsJson = JSONUtils.convertCollectionToJson((ArrayList<Object>)functionResult);
-          return new ResponseEntity<String>(functionResultAsJson, headers, HttpStatus.OK);  
+          return new ResponseEntity<>(functionResultAsJson, headers, HttpStatus.OK);
         } catch (JSONException e) {
           throw new GemfireRestException("Could not convert function results into Restful (JSON) format!", e);
         }
@@ -242,7 +257,5 @@ public abstract class CommonCrudController extends AbstractBaseController {
     }catch (FunctionException fe){
       throw new GemfireRestException("Server has encountered error while executing the function!", fe);
     }
-    
   }
-  
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java
----------------------------------------------------------------------
diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java
index c31292b..8cec110 100644
--- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java
+++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/FunctionAccessController.java
@@ -17,16 +17,25 @@
 
 package org.apache.geode.rest.internal.web.controllers;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
 import org.apache.geode.cache.LowMemoryException;
-import org.apache.geode.cache.execute.*;
+import org.apache.geode.cache.execute.Execution;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionException;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.internal.logging.LogService;
 import org.apache.geode.rest.internal.web.exception.GemfireRestException;
 import org.apache.geode.rest.internal.web.util.ArrayUtils;
 import org.apache.geode.rest.internal.web.util.JSONUtils;
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
 import org.apache.logging.log4j.Logger;
 import org.json.JSONException;
 import org.springframework.http.HttpHeaders;
@@ -35,9 +44,13 @@ import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Controller;
 import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.*;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
 
 /**
  * The FunctionsController class serving REST Requests related to the function execution
@@ -79,12 +92,14 @@ public class FunctionAccessController extends AbstractBaseController {
   )
   @ApiResponses({
       @ApiResponse(code = 200, message = "OK."),
+      @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+      @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
       @ApiResponse(code = 500, message = "GemFire throws an error or exception.")
   })
   @ResponseBody
   @ResponseStatus(HttpStatus.OK)
   public ResponseEntity<?> list() {
-
+    securityService.authorizeDataRead();
     if (logger.isDebugEnabled()) {
       logger.debug("Listing all registered Functions in GemFire...");
     }
@@ -116,6 +131,8 @@ public class FunctionAccessController extends AbstractBaseController {
   )
   @ApiResponses({
       @ApiResponse(code = 200, message = "OK."),
+      @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+      @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
       @ApiResponse(code = 500, message = "if GemFire throws an error or exception"),
       @ApiResponse(code = 400, message = "if Function arguments specified as JSON document in the request body is invalid")
   })
@@ -128,6 +145,7 @@ public class FunctionAccessController extends AbstractBaseController {
       @RequestParam(value = "filter", required = false) final String[] filter,
       @RequestBody(required = false) final String argsInBody
   ) {
+    securityService.authorizeDataWrite();
     Execution function = null;
     functionId = decode(functionId);
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java
----------------------------------------------------------------------
diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java
index dd77316..c05845a 100644
--- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java
+++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/PdxBasedCrudController.java
@@ -20,6 +20,16 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.rest.internal.web.controllers.support.JSONTypes;
+import org.apache.geode.rest.internal.web.controllers.support.RegionData;
+import org.apache.geode.rest.internal.web.controllers.support.RegionEntryData;
+import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException;
+import org.apache.geode.rest.internal.web.util.ArrayUtils;
 import org.apache.logging.log4j.Logger;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
@@ -33,17 +43,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 
-import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.internal.util.ArrayUtils;
-import org.apache.geode.rest.internal.web.controllers.support.JSONTypes;
-import org.apache.geode.rest.internal.web.controllers.support.RegionData;
-import org.apache.geode.rest.internal.web.controllers.support.RegionEntryData;
-import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException;
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
-
 /**
  * The PdxBasedCrudController class serving REST Requests related to the REST CRUD operation on region
  * <p/>
@@ -88,6 +87,8 @@ public class PdxBasedCrudController extends CommonCrudController {
   @ApiResponses( {
     @ApiResponse( code = 201, message = "Created."),
     @ApiResponse( code = 400, message = "Data specified (JSON doc) in the request body is invalid." ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "Region does not exist." ),
     @ApiResponse( code = 409, message = "Key already exist in region."),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")   
@@ -95,7 +96,7 @@ public class PdxBasedCrudController extends CommonCrudController {
   public ResponseEntity<?> create(@PathVariable("region") String region,
       @RequestParam(value = "key", required = false) String key,
       @RequestBody final String json) {
-    
+    securityService.authorizeRegionWrite(region);
     key = generateKey(key);
     
     if(logger.isDebugEnabled()){
@@ -141,12 +142,14 @@ public class PdxBasedCrudController extends CommonCrudController {
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK."),
     @ApiResponse( code = 400, message = "Bad request." ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "Region does not exist." ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")    
   } )
   public ResponseEntity<?> read(@PathVariable("region") String region,
       @RequestParam(value = "limit", defaultValue = DEFAULT_GETALL_RESULT_LIMIT) final String limit) {
-    
+    securityService.authorizeRegionRead(region);
     if(logger.isDebugEnabled()){
       logger.debug("Reading all data in Region ({})...", region);
     }
@@ -219,6 +222,8 @@ public class PdxBasedCrudController extends CommonCrudController {
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK."),
     @ApiResponse( code = 400, message = "Bad Request."),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "Region does not exist." ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")  
   } )
@@ -226,7 +231,9 @@ public class PdxBasedCrudController extends CommonCrudController {
       @PathVariable("region") String region,
       @PathVariable("keys") final String[] keys,
       @RequestParam(value = "ignoreMissingKey", required = false ) final String ignoreMissingKey) {
-    
+
+    for (String key : keys)
+      securityService.authorizeRegionRead(region, key);
     if(logger.isDebugEnabled()){
       logger.debug("Reading data for keys ({}) in Region ({})",
           ArrayUtils.toString(keys), region);
@@ -302,6 +309,8 @@ public class PdxBasedCrudController extends CommonCrudController {
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK."),
     @ApiResponse( code = 400, message = "Bad Request."),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "Region does not exist or if key is not mapped to some value for REPLACE or CAS."),
     @ApiResponse( code = 409, message = "For CAS, @old value does not match to the current value in region" ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")
@@ -310,7 +319,8 @@ public class PdxBasedCrudController extends CommonCrudController {
       @PathVariable("keys") final String[] keys,
       @RequestParam(value = "op", defaultValue = "PUT") final String opValue,
       @RequestBody final String json) {
-    
+    for (String key : keys)
+      securityService.authorizeRegionWrite(region, key);
     if(logger.isDebugEnabled()){
       logger.debug("updating key(s) for region ({}) ", region);
     }
@@ -334,11 +344,13 @@ public class PdxBasedCrudController extends CommonCrudController {
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK."),
     @ApiResponse( code = 400, message = "Bad request." ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "Region does not exist." ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception.")    
   } )
   public ResponseEntity<?> size(@PathVariable("region") String region) {
-    
+    securityService.authorizeRegionRead(region);
     if(logger.isDebugEnabled()){
       logger.debug("Determining the number of entries in Region ({})...", region);
     }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ed443d5/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java
----------------------------------------------------------------------
diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java
index 4f059a4..2df95aa 100644
--- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java
+++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/controllers/QueryAccessController.java
@@ -19,20 +19,10 @@ package org.apache.geode.rest.internal.web.controllers;
 
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.logging.log4j.Logger;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiResponse;
+import com.wordnik.swagger.annotations.ApiResponses;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.query.FunctionDomainException;
 import org.apache.geode.cache.query.NameResolutionException;
@@ -48,10 +38,20 @@ import org.apache.geode.rest.internal.web.exception.GemfireRestException;
 import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException;
 import org.apache.geode.rest.internal.web.util.JSONUtils;
 import org.apache.geode.rest.internal.web.util.ValidationUtils;
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiResponse;
-import com.wordnik.swagger.annotations.ApiResponses;
+import org.apache.logging.log4j.Logger;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
 
 /**
  * The QueryingController class serves all HTTP REST requests related to the gemfire querying
@@ -86,37 +86,39 @@ public class QueryAccessController extends AbstractBaseController {
   }
   
   /**
-   * list all parameterized Queries created in a Gemfire data node
+   * list all parametrized Queries created in a Gemfire data node
    * @return result as a JSON document.
    */
   @RequestMapping(method = RequestMethod.GET,  produces = { MediaType.APPLICATION_JSON_VALUE })
   @ApiOperation(
-    value = "list all parameterized queries",
-    notes = "List all parameterized queries by id/name",
+    value = "list all parametrized queries",
+    notes = "List all parametrized queries by id/name",
     response  = void.class
   )
   @ApiResponses( {
-    @ApiResponse( code = 200, message = "OK." ),  
-    @ApiResponse( code = 500, message = "if GemFire throws an error or exception" )   
+    @ApiResponse( code = 200, message = "OK." ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
+    @ApiResponse( code = 500, message = "if GemFire throws an error or exception" )
   } )
   @ResponseBody
   @ResponseStatus(HttpStatus.OK)
   public ResponseEntity<?> list() {
- 
+    securityService.authorizeDataRead();
     if (logger.isDebugEnabled()) {
-      logger.debug("Listing all parameterized Queries in GemFire...");
+      logger.debug("Listing all parametrized Queries in GemFire...");
     }
     
-    final Region<String, String> parameterizedQueryRegion = getQueryStore(PARAMETERIZED_QUERIES_REGION);
+    final Region<String, String> parametrizedQueryRegion = getQueryStore(PARAMETERIZED_QUERIES_REGION);
     
-    String queryListAsJson =  JSONUtils.formulateJsonForListQueriesCall(parameterizedQueryRegion);
+    String queryListAsJson =  JSONUtils.formulateJsonForListQueriesCall(parametrizedQueryRegion);
     final HttpHeaders headers = new HttpHeaders();  
     headers.setLocation(toUri("queries"));
     return new ResponseEntity<String>(queryListAsJson, headers, HttpStatus.OK);
   } 
   
   /**
-   * Create a named, parameterized Query
+   * Create a named, parametrized Query
    * @param queryId uniquely identify the query
    * @param oqlInUrl OQL query string specified in a request URL
    * @param oqlInBody OQL query string specified in a request body
@@ -124,23 +126,26 @@ public class QueryAccessController extends AbstractBaseController {
    */
   @RequestMapping(method = RequestMethod.POST)
   @ApiOperation(
-    value = "create a parameterized Query",
-    notes = "Prepare the specified parameterized query and assign the corresponding ID for lookup",
+    value = "create a parametrized Query",
+    notes = "Prepare the specified parametrized query and assign the corresponding ID for lookup",
     response  = void.class
   )
   @ApiResponses( {
     @ApiResponse( code = 201, message = "Successfully created." ),
-    @ApiResponse( code = 409, message = "QueryId already assigned to other query." ),  
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
+    @ApiResponse( code = 409, message = "QueryId already assigned to other query." ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception." )
   } )
   public ResponseEntity<?> create(@RequestParam("id") final String queryId,
                                   @RequestParam(value = "q", required = false) String oqlInUrl,
                                   @RequestBody(required = false) final String oqlInBody)
   {
+    securityService.authorizeDataWrite();
     final String oqlStatement = validateQuery(oqlInUrl, oqlInBody);
     
     if (logger.isDebugEnabled()) {
-      logger.debug("Creating a named, parameterized Query ({}) with ID ({})...", oqlStatement, queryId);
+      logger.debug("Creating a named, parametrized Query ({}) with ID ({})...", oqlStatement, queryId);
     }
 
     // store the compiled OQL statement with 'queryId' as the Key into the hidden, ParameterizedQueries Region...
@@ -170,12 +175,14 @@ public class QueryAccessController extends AbstractBaseController {
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "OK." ),
-    @ApiResponse( code = 500, message = "GemFire throws an error or exception" )   
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
+    @ApiResponse( code = 500, message = "GemFire throws an error or exception" )
   } )
   @ResponseBody
   @ResponseStatus(HttpStatus.OK)
   public ResponseEntity<String> runAdhocQuery(@RequestParam("q") String oql) {
-    
+    securityService.authorizeDataRead();
     if (logger.isDebugEnabled()) {
       logger.debug("Running an adhoc Query ({})...", oql);
     }
@@ -210,19 +217,21 @@ public class QueryAccessController extends AbstractBaseController {
   }
 
   /**
-   * Run named parameterized Query with ID
+   * Run named parametrized Query with ID
    * @param queryId id of the OQL string
    * @param arguments query bind params required while executing query
    * @return query result as a JSON document
    */
   @RequestMapping(method = RequestMethod.POST, value = "/{query}", produces = {MediaType.APPLICATION_JSON_VALUE})
   @ApiOperation(
-    value = "run parameterized query",
+    value = "run parametrized query",
     notes = "run the specified named query passing in scalar values for query parameters in the GemFire cluster",
     response  = void.class
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "Query successfully executed." ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 400, message = "Query bind params specified as JSON document in the request body is invalid" ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception" )   
   } )
@@ -231,6 +240,7 @@ public class QueryAccessController extends AbstractBaseController {
   public ResponseEntity<String> runNamedQuery(@PathVariable("query") String queryId,
                                               @RequestBody String arguments)
   {
+    securityService.authorizeDataWrite();
     if (logger.isDebugEnabled()) {
       logger.debug("Running named Query with ID ({})...", queryId);
     }
@@ -286,30 +296,32 @@ public class QueryAccessController extends AbstractBaseController {
   }
 
   /**
-   * Update named, parameterized Query
+   * Update named, parametrized Query
    * @param queryId uniquely identify the query
    * @param oqlInUrl OQL query string specified in a request URL
    * @param oqlInBody OQL query string specified in a request body
    */
   @RequestMapping(method = RequestMethod.PUT, value = "/{query}")
   @ApiOperation(
-    value = "update parameterized query",
-    notes = "Update named, parameterized query by ID",
+    value = "update parametrized query",
+    notes = "Update named, parametrized query by ID",
     response  = void.class
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "Updated successfully." ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "queryId does not exist." ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception." )   
   } )
   public ResponseEntity<?> update( @PathVariable("query") final String queryId,
                                    @RequestParam(value = "q", required = false) String oqlInUrl,
                                    @RequestBody(required = false) final String oqlInBody) {
-    
+    securityService.authorizeDataWrite();
     final String oqlStatement = validateQuery(oqlInUrl, oqlInBody);
 
     if (logger.isDebugEnabled()) {
-      logger.debug("Updating a named, parameterized Query ({}) with ID ({})...", oqlStatement, queryId);
+      logger.debug("Updating a named, parametrized Query ({}) with ID ({})...", oqlStatement, queryId);
     }
 
     // update the OQL statement with 'queryId' as the Key into the hidden, ParameterizedQueries Region...
@@ -320,26 +332,28 @@ public class QueryAccessController extends AbstractBaseController {
     return new ResponseEntity<Object>(HttpStatus.OK);
   }
 
-  //delete named, parameterized query
+  //delete named, parametrized query
   /**
-   * Delete named, parameterized Query
+   * Delete named, parametrized Query
    * @param queryId uniquely identify the query to be deleted
    */
   @RequestMapping(method = RequestMethod.DELETE, value = "/{query}")
   @ApiOperation(
-    value = "delete parameterized query",
-    notes = "delete named, parameterized query by ID",
+    value = "delete parametrized query",
+    notes = "delete named, parametrized query by ID",
     response  = void.class
   )
   @ApiResponses( {
     @ApiResponse( code = 200, message = "Deleted successfully." ),
+    @ApiResponse( code = 401, message = "Invalid Username or Password." ),
+    @ApiResponse( code = 403, message = "Insufficient privileges for operation." ),
     @ApiResponse( code = 404, message = "queryId does not exist." ),
     @ApiResponse( code = 500, message = "GemFire throws an error or exception" )   
   } )
   public ResponseEntity<?> delete(@PathVariable("query") final String queryId) {
-
+    securityService.authorizeDataWrite();
     if (logger.isDebugEnabled()) {
-      logger.debug("Deleting a named, parameterized Query with ID ({}).", queryId);
+      logger.debug("Deleting a named, parametrized Query with ID ({}).", queryId);
     }
     
     //delete the OQL statement with 'queryId' as the Key into the hidden,



Mime
View raw message