You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by pr...@apache.org on 2018/01/11 20:03:16 UTC

[geode] branch develop updated: GEODE-3974: Improve permissions for geode-lucene functions

This is an automated email from the ASF dual-hosted git repository.

prhomberg pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new 740289c  GEODE-3974: Improve permissions for geode-lucene functions
740289c is described below

commit 740289c61d60256c6270756bc84b9e24b76e4913
Author: Patrick Rhomberg <Pu...@users.noreply.github.com>
AuthorDate: Thu Jan 11 12:03:13 2018 -0800

    GEODE-3974: Improve permissions for geode-lucene functions
---
 .../cli/functions/LuceneCreateIndexFunction.java   |  14 +-
 .../cli/functions/LuceneDescribeIndexFunction.java |  13 +
 .../cli/functions/LuceneDestroyIndexFunction.java  |  16 +-
 .../cli/functions/LuceneListIndexFunction.java     |  12 +
 .../cli/functions/LuceneSearchIndexFunction.java   |  12 +-
 .../internal/directory/DumpDirectoryFiles.java     |  13 +
 .../internal/distributed/LuceneQueryFunction.java  |   1 -
 .../distributed/WaitUntilFlushedFunction.java      |   1 -
 .../internal/results/LuceneGetPageFunction.java    |   1 -
 .../lucene/test/LuceneFunctionSecurityTest.java    | 485 +++++++++++++++++++++
 10 files changed, 560 insertions(+), 8 deletions(-)

diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneCreateIndexFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneCreateIndexFunction.java
index b1b974d..df8bf30 100644
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneCreateIndexFunction.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneCreateIndexFunction.java
@@ -18,6 +18,9 @@ package org.apache.geode.cache.lucene.internal.cli.functions;
 import static org.apache.geode.cache.lucene.internal.LuceneServiceImpl.validateCommandParameters.INDEX_NAME;
 import static org.apache.geode.cache.lucene.internal.LuceneServiceImpl.validateCommandParameters.REGION_PATH;
 
+import java.util.Collection;
+import java.util.Collections;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
@@ -33,11 +36,15 @@ import org.apache.geode.cache.lucene.internal.LuceneServiceImpl;
 import org.apache.geode.cache.lucene.internal.cli.LuceneCliStrings;
 import org.apache.geode.cache.lucene.internal.cli.LuceneIndexDetails;
 import org.apache.geode.cache.lucene.internal.cli.LuceneIndexInfo;
+import org.apache.geode.cache.lucene.internal.security.LucenePermission;
 import org.apache.geode.internal.InternalEntity;
 import org.apache.geode.management.internal.cli.CliUtil;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.configuration.domain.XmlEntity;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.ResourcePermission.Operation;
+import org.apache.geode.security.ResourcePermission.Resource;
 
 
 /**
@@ -110,6 +117,12 @@ public class LuceneCreateIndexFunction implements InternalEntity, Function {
     }
   }
 
+  @Override
+  public Collection<ResourcePermission> getRequiredPermissions(String regionName) {
+    return Collections.singleton(
+        new ResourcePermission(Resource.CLUSTER, Operation.MANAGE, LucenePermission.TARGET));
+  }
+
   private LuceneSerializer toSerializer(String serializerName)
       throws InstantiationException, IllegalAccessException, ClassNotFoundException {
     String trimmedName = StringUtils.trim(serializerName);
@@ -136,5 +149,4 @@ public class LuceneCreateIndexFunction implements InternalEntity, Function {
         CliUtil.forName(className, LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER);
     return CliUtil.newInstance(clazz, LuceneCliStrings.LUCENE_CREATE_INDEX__ANALYZER);
   }
-
 }
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunction.java
index dd90116..8f9bac3 100755
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunction.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneDescribeIndexFunction.java
@@ -15,6 +15,9 @@
 
 package org.apache.geode.cache.lucene.internal.cli.functions;
 
+import java.util.Collection;
+import java.util.Collections;
+
 import org.apache.geode.cache.Cache;
 import org.apache.geode.cache.execute.Function;
 import org.apache.geode.cache.execute.FunctionContext;
@@ -25,7 +28,11 @@ import org.apache.geode.cache.lucene.internal.LuceneIndexImpl;
 import org.apache.geode.cache.lucene.internal.LuceneServiceImpl;
 import org.apache.geode.cache.lucene.internal.cli.LuceneIndexDetails;
 import org.apache.geode.cache.lucene.internal.cli.LuceneIndexInfo;
+import org.apache.geode.cache.lucene.internal.security.LucenePermission;
 import org.apache.geode.internal.InternalEntity;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.ResourcePermission.Operation;
+import org.apache.geode.security.ResourcePermission.Resource;
 
 /**
  * The LuceneDescribeIndexFunction class is a function used to collect the information on a
@@ -66,4 +73,10 @@ public class LuceneDescribeIndexFunction implements InternalEntity, Function {
     }
     context.getResultSender().lastResult(result);
   }
+
+  @Override
+  public Collection<ResourcePermission> getRequiredPermissions(String regionName) {
+    return Collections.singleton(
+        new ResourcePermission(Resource.CLUSTER, Operation.READ, LucenePermission.TARGET));
+  }
 }
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneDestroyIndexFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneDestroyIndexFunction.java
index 9803192..1a12894 100644
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneDestroyIndexFunction.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneDestroyIndexFunction.java
@@ -14,6 +14,9 @@
  */
 package org.apache.geode.cache.lucene.internal.cli.functions;
 
+import java.util.Collection;
+import java.util.Collections;
+
 import org.apache.commons.lang.StringUtils;
 
 import org.apache.geode.cache.execute.Function;
@@ -22,16 +25,19 @@ import org.apache.geode.cache.lucene.LuceneService;
 import org.apache.geode.cache.lucene.LuceneServiceProvider;
 import org.apache.geode.cache.lucene.internal.LuceneServiceImpl;
 import org.apache.geode.cache.lucene.internal.cli.LuceneDestroyIndexInfo;
+import org.apache.geode.cache.lucene.internal.security.LucenePermission;
 import org.apache.geode.cache.lucene.internal.xml.LuceneXmlConstants;
 import org.apache.geode.internal.InternalEntity;
 import org.apache.geode.internal.cache.xmlcache.CacheXml;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.configuration.domain.XmlEntity;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.ResourcePermission.Operation;
+import org.apache.geode.security.ResourcePermission.Resource;
 
 public class LuceneDestroyIndexFunction implements Function, InternalEntity {
-
   public void execute(final FunctionContext context) {
-    CliFunctionResult result = null;
+    CliFunctionResult result;
     String memberId = context.getCache().getDistributedSystem().getDistributedMember().getId();
     try {
       LuceneDestroyIndexInfo indexInfo = (LuceneDestroyIndexInfo) context.getArguments();
@@ -66,4 +72,10 @@ public class LuceneDestroyIndexFunction implements Function, InternalEntity {
     return new XmlEntity(CacheXml.REGION, "name", regionName, LuceneXmlConstants.PREFIX,
         LuceneXmlConstants.NAMESPACE, LuceneXmlConstants.INDEX, "name", indexName);
   }
+
+  @Override
+  public Collection<ResourcePermission> getRequiredPermissions(String regionName) {
+    return Collections.singleton(
+        new ResourcePermission(Resource.CLUSTER, Operation.MANAGE, LucenePermission.TARGET));
+  }
 }
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneListIndexFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneListIndexFunction.java
index 34d445b..31c8122 100755
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneListIndexFunction.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneListIndexFunction.java
@@ -15,6 +15,8 @@
 
 package org.apache.geode.cache.lucene.internal.cli.functions;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -27,7 +29,11 @@ import org.apache.geode.cache.lucene.internal.LuceneIndexCreationProfile;
 import org.apache.geode.cache.lucene.internal.LuceneIndexImpl;
 import org.apache.geode.cache.lucene.internal.LuceneServiceImpl;
 import org.apache.geode.cache.lucene.internal.cli.LuceneIndexDetails;
+import org.apache.geode.cache.lucene.internal.security.LucenePermission;
 import org.apache.geode.internal.InternalEntity;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.ResourcePermission.Operation;
+import org.apache.geode.security.ResourcePermission.Resource;
 
 /**
  * The LuceneListIndexFunction class is a function used to collect the information on all lucene
@@ -64,4 +70,10 @@ public class LuceneListIndexFunction implements InternalEntity, Function {
     }
     context.getResultSender().lastResult(indexDetailsSet);
   }
+
+  @Override
+  public Collection<ResourcePermission> getRequiredPermissions(String regionName) {
+    return Collections.singleton(
+        new ResourcePermission(Resource.CLUSTER, Operation.READ, LucenePermission.TARGET));
+  }
 }
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneSearchIndexFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneSearchIndexFunction.java
index 0a6cc3e..c043388 100755
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneSearchIndexFunction.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/cli/functions/LuceneSearchIndexFunction.java
@@ -15,14 +15,14 @@
 
 package org.apache.geode.cache.lucene.internal.cli.functions;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.geode.cache.Cache;
-import org.apache.geode.cache.CacheFactory;
 import org.apache.geode.cache.execute.Function;
-import org.apache.geode.cache.execute.FunctionAdapter;
 import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.cache.lucene.LuceneQuery;
 import org.apache.geode.cache.lucene.LuceneQueryException;
@@ -35,6 +35,9 @@ import org.apache.geode.cache.lucene.internal.cli.LuceneIndexInfo;
 import org.apache.geode.cache.lucene.internal.cli.LuceneQueryInfo;
 import org.apache.geode.cache.lucene.internal.cli.LuceneSearchResults;
 import org.apache.geode.internal.InternalEntity;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.ResourcePermission.Operation;
+import org.apache.geode.security.ResourcePermission.Resource;
 
 /**
  * The LuceneSearchIndexFunction class is a function used to collect the information on a particular
@@ -95,4 +98,9 @@ public class LuceneSearchIndexFunction<K, V> implements InternalEntity, Function
       context.getResultSender().lastResult(result);
     }
   }
+
+  @Override
+  public Collection<ResourcePermission> getRequiredPermissions(String regionName) {
+    return Collections.singleton(new ResourcePermission(Resource.DATA, Operation.READ, regionName));
+  }
 }
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/directory/DumpDirectoryFiles.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/directory/DumpDirectoryFiles.java
index 910f50f..4d720da 100644
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/directory/DumpDirectoryFiles.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/directory/DumpDirectoryFiles.java
@@ -17,6 +17,8 @@ package org.apache.geode.cache.lucene.internal.directory;
 
 import java.io.File;
 import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.lucene.index.IndexWriter;
@@ -35,6 +37,9 @@ import org.apache.geode.cache.lucene.internal.repository.RepositoryManager;
 import org.apache.geode.internal.InternalEntity;
 import org.apache.geode.internal.cache.BucketNotFoundException;
 import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.ResourcePermission.Operation;
+import org.apache.geode.security.ResourcePermission.Resource;
 
 public class DumpDirectoryFiles implements Function, InternalEntity {
   private static final long serialVersionUID = 1L;
@@ -96,4 +101,12 @@ public class DumpDirectoryFiles implements Function, InternalEntity {
   public boolean optimizeForWrite() {
     return true;
   }
+
+  @Override
+  public Collection<ResourcePermission> getRequiredPermissions(String regionName) {
+    Set<ResourcePermission> required = new HashSet<>();
+    required.add(new ResourcePermission(Resource.DATA, Operation.READ, regionName));
+    required.add(new ResourcePermission(Resource.CLUSTER, Operation.MANAGE));
+    return required;
+  }
 }
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java
index 0b104a3..bc5ced6 100644
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/LuceneQueryFunction.java
@@ -19,7 +19,6 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Optional;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.lucene.search.Query;
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/WaitUntilFlushedFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/WaitUntilFlushedFunction.java
index c9e10d9..f0c88a4 100644
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/WaitUntilFlushedFunction.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/distributed/WaitUntilFlushedFunction.java
@@ -17,7 +17,6 @@ package org.apache.geode.cache.lucene.internal.distributed;
 
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.geode.cache.Cache;
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/results/LuceneGetPageFunction.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/results/LuceneGetPageFunction.java
index 07dc1ad..8e2bfcc 100644
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/results/LuceneGetPageFunction.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/results/LuceneGetPageFunction.java
@@ -18,7 +18,6 @@ package org.apache.geode.cache.lucene.internal.results;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
 import java.util.Set;
 
 import org.apache.logging.log4j.Logger;
diff --git a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/LuceneFunctionSecurityTest.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/LuceneFunctionSecurityTest.java
new file mode 100644
index 0000000..2fa054e
--- /dev/null
+++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/LuceneFunctionSecurityTest.java
@@ -0,0 +1,485 @@
+/*
+ * 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.cache.lucene.test;
+
+import static org.apache.geode.management.internal.security.ResourcePermissions.CLUSTER_MANAGE;
+import static org.apache.geode.management.internal.security.ResourcePermissions.DATA_READ;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+
+import java.util.function.Predicate;
+
+import org.assertj.core.api.Condition;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.Mockito;
+
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.cache.lucene.internal.cli.functions.LuceneCreateIndexFunction;
+import org.apache.geode.cache.lucene.internal.cli.functions.LuceneDescribeIndexFunction;
+import org.apache.geode.cache.lucene.internal.cli.functions.LuceneDestroyIndexFunction;
+import org.apache.geode.cache.lucene.internal.cli.functions.LuceneListIndexFunction;
+import org.apache.geode.cache.lucene.internal.cli.functions.LuceneSearchIndexFunction;
+import org.apache.geode.cache.lucene.internal.directory.DumpDirectoryFiles;
+import org.apache.geode.cache.lucene.internal.distributed.LuceneQueryFunction;
+import org.apache.geode.cache.lucene.internal.distributed.WaitUntilFlushedFunction;
+import org.apache.geode.cache.lucene.internal.results.LuceneGetPageFunction;
+import org.apache.geode.cache.lucene.internal.security.LucenePermission;
+import org.apache.geode.examples.SimpleSecurityManager;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.ResourcePermission.Operation;
+import org.apache.geode.security.ResourcePermission.Resource;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.junit.categories.SecurityTest;
+import org.apache.geode.test.junit.rules.ConnectionConfiguration;
+import org.apache.geode.test.junit.rules.GfshCommandRule;
+import org.apache.geode.test.junit.rules.ServerStarterRule;
+
+@Category({IntegrationTest.class, SecurityTest.class})
+public class LuceneFunctionSecurityTest {
+  // Note: this region name is embedded below in several @ConnectionConfiguration inputs,
+  // which is itself case-sensitive in parsing.
+  private static String regionName = "this_test_region";
+
+  private static ResourcePermission CLUSTER_MANAGE_LUCENE =
+      new ResourcePermission(Resource.CLUSTER, Operation.MANAGE, LucenePermission.TARGET);
+  private static ResourcePermission CLUSTER_READ_LUCENE =
+      new ResourcePermission(Resource.CLUSTER, Operation.READ, LucenePermission.TARGET);
+  private static ResourcePermission DATA_READ_REGION =
+      new ResourcePermission(Resource.DATA, Operation.READ, regionName);
+
+  private static Function luceneCreateIndexFunction = Mockito.spy(new LuceneCreateIndexFunction());
+  private static Function luceneDescribeIndexFunction =
+      Mockito.spy(new LuceneDescribeIndexFunction());
+  private static Function luceneDestroyIndexFunction =
+      Mockito.spy(new LuceneDestroyIndexFunction());
+  private static Function luceneListIndexFunction = Mockito.spy(new LuceneListIndexFunction());
+  private static Function luceneSearchIndexFunction = Mockito.spy(new LuceneSearchIndexFunction());
+  private static Function dumpDirectoryFiles = Mockito.spy(new DumpDirectoryFiles());
+  private static Function luceneQueryFunction = Mockito.spy(new LuceneQueryFunction());
+  private static Function waitUntilFlushedFunction = Mockito.spy(new WaitUntilFlushedFunction());
+  private static Function luceneGetPageFunction = Mockito.spy(new LuceneGetPageFunction());
+
+  static {
+    Mockito.doNothing().when(luceneCreateIndexFunction).execute(any());
+    Mockito.doNothing().when(luceneDescribeIndexFunction).execute(any());
+    Mockito.doNothing().when(luceneDestroyIndexFunction).execute(any());
+    Mockito.doNothing().when(luceneListIndexFunction).execute(any());
+    Mockito.doNothing().when(luceneSearchIndexFunction).execute(any());
+    Mockito.doNothing().when(dumpDirectoryFiles).execute(any());
+    Mockito.doNothing().when(luceneQueryFunction).execute(any());
+    Mockito.doNothing().when(waitUntilFlushedFunction).execute(any());
+    Mockito.doNothing().when(luceneGetPageFunction).execute(any());
+  }
+
+  @ClassRule
+  public static ServerStarterRule server =
+      new ServerStarterRule().withJMXManager().withSecurityManager(SimpleSecurityManager.class)
+          .withRegion(RegionShortcut.PARTITION, regionName).withAutoStart();
+
+  @Rule
+  public GfshCommandRule gfsh =
+      new GfshCommandRule(server::getJmxPort, GfshCommandRule.PortType.jmxManager);
+
+  @BeforeClass
+  public static void setupClass() {
+    FunctionService.registerFunction(luceneCreateIndexFunction);
+    FunctionService.registerFunction(luceneDescribeIndexFunction);
+    FunctionService.registerFunction(luceneDestroyIndexFunction);
+    FunctionService.registerFunction(luceneListIndexFunction);
+    FunctionService.registerFunction(luceneSearchIndexFunction);
+    FunctionService.registerFunction(dumpDirectoryFiles);
+    FunctionService.registerFunction(luceneQueryFunction);
+    FunctionService.registerFunction(waitUntilFlushedFunction);
+    FunctionService.registerFunction(luceneGetPageFunction);
+  }
+
+  /* Command authorized tests */
+  @Test
+  @ConnectionConfiguration(user = "clusterManageLucene", password = "clusterManageLucene")
+  public void testValidPermissionsForLuceneCreateIndexFunction() throws Exception {
+    Function thisFunction = luceneCreateIndexFunction;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "clusterReadLucene", password = "clusterReadLucene")
+  public void testValidPermissionsForLuceneDescribeIndexFunction() throws Exception {
+    Function thisFunction = luceneDescribeIndexFunction;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "clusterManageLucene", password = "clusterManageLucene")
+  public void testValidPermissionsForLuceneDestroyIndexFunction() throws Exception {
+    Function thisFunction = luceneDestroyIndexFunction;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "clusterReadLucene", password = "clusterReadLucene")
+  public void testValidPermissionsForLuceneListIndexFunction() throws Exception {
+    Function thisFunction = luceneListIndexFunction;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataReadThis_test_region,clusterManage",
+      password = "dataReadThis_test_region,clusterManage")
+  public void testValidPermissionsForDumpDirectoryFilesWithRegionParameter() throws Exception {
+    Function thisFunction = dumpDirectoryFiles;
+
+    gfsh.executeAndAssertThat(
+        "execute function  --region=" + regionName + " --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataRead,clusterManage", password = "dataRead,clusterManage")
+  public void testValidPermissionsForDumpDirectoryFilesWithoutRegionParameter() throws Exception {
+    Function thisFunction = dumpDirectoryFiles;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+
+  @Test
+  @ConnectionConfiguration(user = "dataRead", password = "dataRead")
+  public void testValidPermissionsForLuceneSearchIndexFunctionWithoutRegionParameter()
+      throws Exception {
+    Function thisFunction = luceneSearchIndexFunction;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataReadThis_test_region", password = "dataReadThis_test_region")
+  public void testValidPermissionsForLuceneSearchIndexFunctionWithRegionParameter()
+      throws Exception {
+    Function thisFunction = luceneSearchIndexFunction;
+
+    gfsh.executeAndAssertThat(
+        "execute function --region=" + regionName + " --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataRead", password = "dataRead")
+  public void testValidPermissionsForLuceneQueryFunctionWithoutRegionParameter() throws Exception {
+    Function thisFunction = luceneQueryFunction;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataReadThis_test_region", password = "dataReadThis_test_region")
+  public void testValidPermissionsForLuceneQueryFunctionWithRegionParameter() throws Exception {
+    Function thisFunction = luceneQueryFunction;
+
+    gfsh.executeAndAssertThat(
+        "execute function --region=" + regionName + " --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataRead", password = "dataRead")
+  public void testValidPermissionsForWaitUntilFlushedFunctionWithoutRegionParameter()
+      throws Exception {
+    Function thisFunction = waitUntilFlushedFunction;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataReadThis_test_region", password = "dataReadThis_test_region")
+  public void testValidPermissionsForWaitUntilFlushedFunctionWithRegionParameter()
+      throws Exception {
+    Function thisFunction = waitUntilFlushedFunction;
+
+    gfsh.executeAndAssertThat(
+        "execute function --region=" + regionName + " --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataRead", password = "dataRead")
+  public void testValidPermissionsForLuceneGetPageFunctionWithoutRegionParameter()
+      throws Exception {
+    Function thisFunction = luceneGetPageFunction;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataReadThis_test_region", password = "dataReadThis_test_region")
+  public void testValidPermissionsForLuceneGetPageFunctionWithRegionParameter() throws Exception {
+    Function thisFunction = luceneGetPageFunction;
+
+    gfsh.executeAndAssertThat(
+        "execute function --region=" + regionName + " --id=" + thisFunction.getId())
+        .doesNotContainOutput("not authorized for").statusIsSuccess();
+  }
+
+
+  /* Command refused tests */
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneCreateIndexFunction() throws Exception {
+    Function thisFunction = luceneCreateIndexFunction;
+    ResourcePermission thisRequiredPermission = CLUSTER_MANAGE_LUCENE;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneDescribeIndexFunction() throws Exception {
+    Function thisFunction = luceneDescribeIndexFunction;
+    ResourcePermission thisRequiredPermission = CLUSTER_READ_LUCENE;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneDestroyIndexFunction() throws Exception {
+    Function thisFunction = luceneDestroyIndexFunction;
+    ResourcePermission thisRequiredPermission = CLUSTER_MANAGE_LUCENE;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneListIndexFunction() throws Exception {
+    Function thisFunction = luceneListIndexFunction;
+    ResourcePermission thisRequiredPermission = CLUSTER_READ_LUCENE;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForDumpDirectoryFilesWithoutRegionParameter_noPermission()
+      throws Exception {
+    Function thisFunction = dumpDirectoryFiles;
+
+    Predicate<String> notAuthForDataRead =
+        s -> s.contains("not authorized for " + DATA_READ.toString());
+    Predicate<String> notAuthForClusterManage =
+        s -> s.contains("not authorized for " + CLUSTER_MANAGE.toString());
+    Predicate<String> notAuthForSomePermission =
+        s -> notAuthForDataRead.test(s) || notAuthForClusterManage.test(s);
+
+    String output = gfsh.execute("execute function --id=" + thisFunction.getId());
+
+    Condition<String> containsSomeAuthFailure = new Condition<>(notAuthForSomePermission,
+        "not authorized for for [DATA:MANAGE|CLUSTER:MANAGE]", output);
+    assertThat(output).has(containsSomeAuthFailure);
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataRead", password = "dataRead")
+  public void testInvalidPermissionsForDumpDirectoryFilesWithoutRegionParameter_withDataRead()
+      throws Exception {
+    Function thisFunction = dumpDirectoryFiles;
+    ResourcePermission thisMissingPermission = CLUSTER_MANAGE;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisMissingPermission.toString()).statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "clusterManage", password = "clusterManage")
+  public void testInvalidPermissionsForDumpDirectoryFilesWithoutRegionParameter_withClusterManage()
+      throws Exception {
+    Function thisFunction = dumpDirectoryFiles;
+    ResourcePermission thisMissingPermission = DATA_READ;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisMissingPermission.toString()).statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForDumpDirectoryFilesWithRegionParameter_noPermission()
+      throws Exception {
+    Function thisFunction = dumpDirectoryFiles;
+
+    Predicate<String> notAuthForDataReadRegion =
+        s -> s.contains("not authorized for " + DATA_READ_REGION.toString());
+    Predicate<String> notAuthForClusterManage =
+        s -> s.contains("not authorized for " + CLUSTER_MANAGE.toString());
+    Predicate<String> notAuthForSomePermission =
+        s -> notAuthForDataReadRegion.test(s) || notAuthForClusterManage.test(s);
+
+    String output =
+        gfsh.execute("execute function --region=" + regionName + " --id=" + thisFunction.getId());
+
+    Condition<String> containsSomeAuthFailure =
+        new Condition<>(notAuthForSomePermission, "D:R or C:M:L auth failure", output);
+    assertThat(output).has(containsSomeAuthFailure);
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "dataReadThis_test_region", password = "dataReadThis_test_region")
+  public void testInvalidPermissionsForDumpDirectoryFilesWithRegionParameter_withDataReadRegion()
+      throws Exception {
+    Function thisFunction = dumpDirectoryFiles;
+    ResourcePermission thisMissingPermission = CLUSTER_MANAGE;
+
+    gfsh.executeAndAssertThat(
+        "execute function  --region=" + regionName + " --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisMissingPermission.toString()).statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "clusterManage", password = "clusterManage")
+  public void testInvalidPermissionsForDumpDirectoryFilesWithRegionParameter_withClusterManage()
+      throws Exception {
+    Function thisFunction = dumpDirectoryFiles;
+    ResourcePermission thisMissingPermission = DATA_READ;
+
+    gfsh.executeAndAssertThat(
+        "execute function  --region=" + regionName + " --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisMissingPermission.toString()).statusIsSuccess();
+  }
+
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneSearchIndexFunctionWithoutRegionParameter()
+      throws Exception {
+    Function thisFunction = luceneSearchIndexFunction;
+    ResourcePermission thisRequiredPermission = DATA_READ;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneSearchIndexFunctionWithRegionParameter()
+      throws Exception {
+    Function thisFunction = luceneSearchIndexFunction;
+    ResourcePermission thisRequiredPermission = DATA_READ_REGION;
+
+    gfsh.executeAndAssertThat(
+        "execute function --region=" + regionName + " --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneQueryFunctionWithoutRegionParameter()
+      throws Exception {
+    Function thisFunction = luceneQueryFunction;
+    ResourcePermission thisRequiredPermission = DATA_READ;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneQueryFunctionWithRegionParameter() throws Exception {
+    Function thisFunction = luceneQueryFunction;
+    ResourcePermission thisRequiredPermission = DATA_READ_REGION;
+
+    gfsh.executeAndAssertThat(
+        "execute function --region=" + regionName + " --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForWaitUntilFlushedFunctionWithoutRegionParameter()
+      throws Exception {
+    Function thisFunction = waitUntilFlushedFunction;
+    ResourcePermission thisRequiredPermission = DATA_READ;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForWaitUntilFlushedFunctionWithRegionParameter()
+      throws Exception {
+    Function thisFunction = waitUntilFlushedFunction;
+    ResourcePermission thisRequiredPermission = DATA_READ_REGION;
+
+    gfsh.executeAndAssertThat(
+        "execute function --region=" + regionName + " --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneGetPageFunctionWithoutRegionParameter()
+      throws Exception {
+    Function thisFunction = luceneGetPageFunction;
+    ResourcePermission thisRequiredPermission = DATA_READ;
+
+    gfsh.executeAndAssertThat("execute function --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+
+  @Test
+  @ConnectionConfiguration(user = "noPermissions", password = "noPermissions")
+  public void testInvalidPermissionsForLuceneGetPageFunctionWithRegionParameter() throws Exception {
+    Function thisFunction = luceneGetPageFunction;
+    ResourcePermission thisRequiredPermission = DATA_READ_REGION;
+
+    gfsh.executeAndAssertThat(
+        "execute function --region=" + regionName + " --id=" + thisFunction.getId())
+        .containsOutput("not authorized for " + thisRequiredPermission.toString())
+        .statusIsSuccess();
+  }
+}

-- 
To stop receiving notification emails like this one, please contact
['"commits@geode.apache.org" <co...@geode.apache.org>'].