CVE-2017-4952: Incorrect Permission Assignment for Critical Resource (CWE-732)
value: VMware Xenon 1.x, prior to 1.5.4-CR7_1, 1.5.7_7, 1.5.4-CR6_2, 1.3.7-CR1_2, 1.1.0-CR0-3, 1.1.0-CR3_1,1.4.2-CR4_1, and 1.5.4_8, contains an authentication bypass vulnerability due to insufficient access controls for utility endpoints. Successful exploitation of this issue may result in information disclosure.
CWE description: The product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors.
CVSS v3 base score: 7.5
Published: 2018-05-02T14:29Z
Repository: https://github.com/vmware/xenon
Language: Java
Files changed: xenon-common/src/main/java/com/vmware/xenon/common/UtilityService.java, xenon-common/src/test/java/com/vmware/xenon/common/TestAuthorization.java, xenon-common/src/test/java/com/vmware/xenon/common/TestExampleServiceHost.java, xenon-common/src/test/java/com/vmware/xenon/common/TestServiceHost.java, xenon-common/src/test/java/com/vmware/xenon/common/TestSubscriptions.java, xenon-common/src/test/java/com/vmware/xenon/common/TestUtilityService.java, xenon-common/src/test/java/com/vmware/xenon/common/test/AuthorizationHelper.java, xenon-common/src/test/java/com/vmware/xenon/common/test/VerificationHost.java, xenon-common/src/test/java/com/vmware/xenon/services/common/TestNodeGroupService.java
Commit date: 2018-02-13 11:53:18 -0800
Commit message: Add auth to UtilityService

Extend auth check to UtiliyService endpoints: stats, config, subscription

Issue: VRXEN-5

Change-Id: I52a4b4a42731c244a97f97610dcaddb6837e67fb

Diff: diff --git a/xenon-common/src/main/java/com/vmware/xenon/common/UtilityService.java b/xenon-common/src/main/java/com/vmware/xenon/common/UtilityService.java
index 82added1..683f93a5 100644
--- a/xenon-common/src/main/java/com/vmware/xenon/common/UtilityService.java
+++ b/xenon-common/src/main/java/com/vmware/xenon/common/UtilityService.java
@@ -139,11 +139,33 @@ public class UtilityService implements Service {
         return this;
     }
 
     @Override
     public void authorizeRequest(Operation op) {
-        op.complete();
+
+        String suffix = UriUtils.buildUriPath(UriUtils.URI_PATH_CHAR, UriUtils.getLastPathSegment(op.getUri()));
+
+        // allow access to ui endpoint
+        if (ServiceHost.SERVICE_URI_SUFFIX_UI.equals(suffix)) {
+            op.complete();
+            return;
+        }
+
+        ServiceDocument doc = new ServiceDocument();
+        if (this.parent.getOptions().contains(ServiceOption.FACTORY_ITEM)) {
+            doc.documentSelfLink = UriUtils.buildUriPath(UriUtils.getParentPath(this.parent.getSelfLink()), suffix);
+        } else {
+            doc.documentSelfLink = UriUtils.buildUriPath(this.parent.getSelfLink(), suffix);
+        }
+
+        doc.documentKind = Utils.buildKind(this.parent.getStateType());
+        if (getHost().isAuthorized(this.parent, doc, op)) {
+            op.complete();
+            return;
+        }
+
+        op.fail(Operation.STATUS_CODE_FORBIDDEN);
     }
 
     @Override
     public void handleRequest(Operation op) {
         String uriPrefix = this.parent.getSelfLink() + ServiceHost.SERVICE_URI_SUFFIX_UI;
diff --git a/xenon-common/src/test/java/com/vmware/xenon/common/TestAuthorization.java b/xenon-common/src/test/java/com/vmware/xenon/common/TestAuthorization.java
index fda80fe7..838ac18e 100644
--- a/xenon-common/src/test/java/com/vmware/xenon/common/TestAuthorization.java
+++ b/xenon-common/src/test/java/com/vmware/xenon/common/TestAuthorization.java
@@ -463,20 +463,24 @@ public class TestAuthorization extends BasicTestCase {
                 Operation.createPatch(this.host, guestLink)
                         .setContentType(Operation.MEDIA_TYPE_APPLICATION_KRYO_OCTET_STREAM)
                         .setBody(state));
         assertEquals(Operation.STATUS_CODE_UNAUTHORIZED, failureResponse.op.getStatusCode());
 
+        OperationContext.setAuthorizationContext(this.host.getSystemAuthorizationContext());
         Map<String, ServiceStats.ServiceStat> stat = this.host.getServiceStats(
                 UriUtils.buildUri(this.host, ServiceUriPaths.CORE_MANAGEMENT));
         double currentInsertCount = stat.get(
                 ServiceHostManagementService.STAT_NAME_AUTHORIZATION_CACHE_INSERT_COUNT).latestValue;
+        OperationContext.setAuthorizationContext(null);
 
         // Make a second request and verify that the cache did not get updated, instead Xenon re-used
         // the cached Guest authorization context.
         sender.sendAndWait(Operation.createGet(this.host, ExampleService.FACTORY_LINK));
+        OperationContext.setAuthorizationContext(this.host.getSystemAuthorizationContext());
         stat = this.host.getServiceStats(
                 UriUtils.buildUri(this.host, ServiceUriPaths.CORE_MANAGEMENT));
+        OperationContext.setAuthorizationContext(null);
         double newInsertCount = stat.get(
                 ServiceHostManagementService.STAT_NAME_AUTHORIZATION_CACHE_INSERT_COUNT).latestValue;
         assertTrue(currentInsertCount == newInsertCount);
 
         // Make sure that Authorization Context cache in Xenon has at least one cached token.
@@ -755,10 +759,20 @@ public class TestAuthorization extends BasicTestCase {
 
                     ctx2.completeIteration();
                 }));
         this.host.testWait(ctx2);
 
+        // do GET on factory /stats, we should get 403
+        Operation statsGet = Operation.createGet(this.host,
+                ExampleService.FACTORY_LINK + ServiceHost.SERVICE_URI_SUFFIX_STATS);
+        this.host.sendAndWaitExpectFailure(statsGet, Operation.STATUS_CODE_FORBIDDEN);
+
+        // do GET on factory /config, we should get 403
+        Operation configGet = Operation.createGet(this.host,
+                ExampleService.FACTORY_LINK + ServiceHost.SERVICE_URI_SUFFIX_CONFIG);
+        this.host.sendAndWaitExpectFailure(configGet, Operation.STATUS_CODE_FORBIDDEN);
+
         // Assume Jane's identity
         this.host.assumeIdentity(this.userServicePath);
         // add docs accessible by jane
         exampleServices.putAll(createExampleServices("jane"));
 
@@ -796,13 +810,31 @@ public class TestAuthorization extends BasicTestCase {
         assertAuthorizedServicesInResult("jane", exampleServices, task.results);
 
         // reset the auth context
         OperationContext.setAuthorizationContext(null);
 
+        // do GET on utility suffixes in example child services, we should get 403
+        for (URI childUri : exampleServices.keySet()) {
+            statsGet = Operation.createGet(this.host,
+                    childUri.getPath() + ServiceHost.SERVICE_URI_SUFFIX_STATS);
+            this.host.sendAndWaitExpectFailure(statsGet, Operation.STATUS_CODE_FORBIDDEN);
+            configGet = Operation.createGet(this.host,
+                    childUri.getPath() + ServiceHost.SERVICE_URI_SUFFIX_CONFIG);
+            this.host.sendAndWaitExpectFailure(configGet, Operation.STATUS_CODE_FORBIDDEN);
+        }
+
         // Assume Jane's identity through header auth token
         String authToken = generateAuthToken(this.userServicePath);
 
+        // do GET on utility suffixes in example child services, we should get 200
+        for (URI childUri : exampleServices.keySet()) {
+            statsGet = Operation.createGet(this.host,
+                    childUri.getPath() + ServiceHost.SERVICE_URI_SUFFIX_STATS);
+            statsGet.addRequestHeader(Operation.REQUEST_AUTH_TOKEN_HEADER, authToken);
+            this.host.sendAndWaitExpectSuccess(statsGet);
+        }
+
         verifyJaneAccess(exampleServices, authToken);
 
         // test user impersonation
         this.host.setSystemAuthorizationContext();
         AuthzStatefulService s = new AuthzStatefulService();
diff --git a/xenon-common/src/test/java/com/vmware/xenon/common/TestExampleServiceHost.java b/xenon-common/src/test/java/com/vmware/xenon/common/TestExampleServiceHost.java
index 572d816c..a3fd5a2c 100644
--- a/xenon-common/src/test/java/com/vmware/xenon/common/TestExampleServiceHost.java
+++ b/xenon-common/src/test/java/com/vmware/xenon/common/TestExampleServiceHost.java
@@ -79,14 +79,10 @@ public class TestExampleServiceHost extends BasicReusableHostTestCase {
     /**
      * Supports createUsers() by logging in as the admin. The admin user
      * isn't created immediately, so this polls.
      */
     private String loginUser(URI hostUri) throws Throwable {
-        URI usersLink = UriUtils.buildUri(hostUri, UserService.FACTORY_LINK);
-        // wait for factory availability
-        this.host.waitForReplicatedFactoryServiceAvailable(usersLink);
-
         String basicAuth = BasicAuthenticationUtils.constructBasicAuth(adminUser, adminUser);
         URI loginUri = UriUtils.buildUri(hostUri, ServiceUriPaths.CORE_AUTHN_BASIC);
         AuthenticationRequest login = new AuthenticationRequest();
         login.requestType = AuthenticationRequest.AuthenticationRequestType.LOGIN;
 
diff --git a/xenon-common/src/test/java/com/vmware/xenon/common/TestServiceHost.java b/xenon-common/src/test/java/com/vmware/xenon/common/TestServiceHost.java
index a720af07..68303f72 100644
--- a/xenon-common/src/test/java/com/vmware/xenon/common/TestServiceHost.java
+++ b/xenon-common/src/test/java/com/vmware/xenon/common/TestServiceHost.java
@@ -420,13 +420,17 @@ public class TestServiceHost {
 
         ri = new RequestRateInfo();
         ri.limit = limit;
         ri.options = EnumSet.of(RequestRateInfo.Option.PAUSE_PROCESSING);
         this.host.setRequestRateLimit(userPath, ri);
-        this.host.assumeIdentity(userPath);
 
+        this.host.setSystemAuthorizationContext();
         ServiceStat rateLimitStatBefore = getRateLimitOpCountStat();
+        this.host.resetSystemAuthorizationContext();
+
+        this.host.assumeIdentity(userPath);
+
         if (rateLimitStatBefore == null) {
             rateLimitStatBefore = new ServiceStat();
             rateLimitStatBefore.latestValue = 0.0;
         }
         TestContext ctx2 = this.host.testCreate(count * states.size());
@@ -441,11 +445,14 @@ public class TestServiceHost {
                 this.host.send(op);
             }
         }
         this.host.testWait(ctx2);
         ctx2.logAfter();
+
+        this.host.setSystemAuthorizationContext();
         ServiceStat rateLimitStatAfter = getRateLimitOpCountStat();
+        this.host.resetSystemAuthorizationContext();
         assertTrue(rateLimitStatAfter.latestValue > rateLimitStatBefore.latestValue);
 
         this.host.setMaintenanceIntervalMicros(
                 TimeUnit.MILLISECONDS.toMicros(VerificationHost.FAST_MAINT_INTERVAL_MILLIS));
 
@@ -471,11 +478,13 @@ public class TestServiceHost {
         }
         this.host.testWait(ctx3);
         ctx3.logAfter();
 
         // verify rate limiting did not happen
+        this.host.setSystemAuthorizationContext();
         ServiceStat rateLimitStatExpectSame = getRateLimitOpCountStat();
+        this.host.resetSystemAuthorizationContext();
         assertTrue(rateLimitStatAfter.latestValue == rateLimitStatExpectSame.latestValue);
     }
 
     @Test
     public void postFailureOnAlreadyStarted() throws Throwable {
@@ -2223,12 +2232,13 @@ public class TestServiceHost {
         return patch;
     }
 
     private ServiceStat getRateLimitOpCountStat() throws Throwable {
         URI managementServiceUri = this.host.getManagementServiceUri();
-        return this.host.getServiceStats(managementServiceUri)
+        ServiceStat stats = this.host.getServiceStats(managementServiceUri)
                 .get(ServiceHostManagementService.STAT_NAME_RATE_LIMITED_OP_COUNT);
+        return stats;
     }
 
     @Test
     public void thirdPartyClientPost() throws Throwable {
         setUp(false);
diff --git a/xenon-common/src/test/java/com/vmware/xenon/common/TestSubscriptions.java b/xenon-common/src/test/java/com/vmware/xenon/common/TestSubscriptions.java
index 209d33e4..66ab7817 100644
--- a/xenon-common/src/test/java/com/vmware/xenon/common/TestSubscriptions.java
+++ b/xenon-common/src/test/java/com/vmware/xenon/common/TestSubscriptions.java
@@ -298,15 +298,18 @@ public class TestSubscriptions extends BasicTestCase {
                 default:
                     break;
 
                 }
             };
+
+            hostWithAuth.setSystemAuthorizationContext();
             Operation subscribe = Operation.createPost(UriUtils.buildUri(hostWithAuth, minimalServiceUUID));
             subscribe.setReferer(hostWithAuth.getReferer());
             ServiceSubscriber subscriber = new ServiceSubscriber();
             subscriber.replayState = true;
             hostWithAuth.startSubscriptionService(subscribe, notifyC, subscriber);
+            hostWithAuth.resetAuthorizationContext();
             hostWithAuth.testWait(notifyContext);
         } finally {
             if (hostWithAuth != null) {
                 hostWithAuth.tearDown();
             }
diff --git a/xenon-common/src/test/java/com/vmware/xenon/common/TestUtilityService.java b/xenon-common/src/test/java/com/vmware/xenon/common/TestUtilityService.java
index 1756bf97..c236d666 100644
--- a/xenon-common/src/test/java/com/vmware/xenon/common/TestUtilityService.java
+++ b/xenon-common/src/test/java/com/vmware/xenon/common/TestUtilityService.java
@@ -12,12 +12,17 @@
  */
 
 package com.vmware.xenon.common;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 
+import static com.vmware.xenon.common.ServiceHost.SERVICE_URI_SUFFIX_SYNCHRONIZATION;
+import static com.vmware.xenon.common.ServiceHost.SERVICE_URI_SUFFIX_TEMPLATE;
+import static com.vmware.xenon.common.ServiceHost.SERVICE_URI_SUFFIX_UI;
+
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
@@ -32,14 +37,20 @@ import com.vmware.xenon.common.Service.ServiceOption;
 import com.vmware.xenon.common.ServiceStats.ServiceStat;
 import com.vmware.xenon.common.ServiceStats.ServiceStatLogHistogram;
 import com.vmware.xenon.common.ServiceStats.TimeSeriesStats;
 import com.vmware.xenon.common.ServiceStats.TimeSeriesStats.AggregationType;
 import com.vmware.xenon.common.ServiceStats.TimeSeriesStats.TimeBin;
+import com.vmware.xenon.common.test.AuthTestUtils;
 import com.vmware.xenon.common.test.TestContext;
+import com.vmware.xenon.common.test.TestRequestSender;
+import com.vmware.xenon.common.test.TestRequestSender.FailureResponse;
+import com.vmware.xenon.common.test.VerificationHost;
+import com.vmware.xenon.services.common.AuthorizationContextService;
 import com.vmware.xenon.services.common.ExampleService;
 import com.vmware.xenon.services.common.ExampleService.ExampleServiceState;
 import com.vmware.xenon.services.common.MinimalTestService;
+import com.vmware.xenon.services.common.QueryTask.Query;
 import com.vmware.xenon.services.common.ServiceUriPaths;
 
 public class TestUtilityService extends BasicReusableHostTestCase {
 
     @Before
@@ -823,6 +834,160 @@ public class TestUtilityService extends BasicReusableHostTestCase {
         assertEquals("stat index 0", "keyAAA", statList.get(0));
         assertEquals("stat index 1", "keyBBB", statList.get(1));
         assertEquals("stat index 2", "keyCCC", statList.get(2));
     }
 
+    @Test
+    public void endpointAuthorization() throws Throwable {
+        VerificationHost host = VerificationHost.create(0);
+        host.setAuthorizationService(new AuthorizationContextService());
+        host.setAuthorizationEnabled(true);
+        host.setMaintenanceIntervalMicros(TimeUnit.MILLISECONDS.toMicros(100));
+        host.start();
+
+        TestRequestSender sender = host.getTestRequestSender();
+
+        host.setSystemAuthorizationContext();
+        host.waitForReplicatedFactoryServiceAvailable(UriUtils.buildUri(host, ExampleService.FACTORY_LINK));
+
+        String exampleUser = "example@vmware.com";
+        String examplePass = "password";
+        TestContext authCtx = host.testCreate(1);
+        AuthorizationSetupHelper.create()
+                .setHost(host)
+                .setUserEmail(exampleUser)
+                .setUserPassword(examplePass)
+                .setResourceQuery(Query.Builder.create()
+                        .addFieldClause(ServiceDocument.FIELD_NAME_KIND, Utils.buildKind(ExampleServiceState.class))
+                        .build())
+                .setCompletion(authCtx.getCompletion())
+                .start();
+        authCtx.await();
+
+        // create a sample service
+        ExampleServiceState doc = new ExampleServiceState();
+        doc.name = "foo";
+        doc.documentSelfLink = "foo";
+
+        Operation post = Operation.createPost(host, ExampleService.FACTORY_LINK).setBody(doc);
+        ExampleServiceState postResult = sender.sendAndWait(post, ExampleServiceState.class);
+
+        host.resetAuthorizationContext();
+
+        URI factoryAvailableUri = UriUtils.buildAvailableUri(host, ExampleService.FACTORY_LINK);
+        URI factoryStatsUri = UriUtils.buildStatsUri(host, ExampleService.FACTORY_LINK);
+        URI factoryConfigUri = UriUtils.buildConfigUri(host, ExampleService.FACTORY_LINK);
+        URI factorySubscriptionUri = UriUtils.buildSubscriptionUri(host, ExampleService.FACTORY_LINK);
+        URI factoryTemplateUri = UriUtils.buildUri(host, UriUtils.buildUriPath(ExampleService.FACTORY_LINK, SERVICE_URI_SUFFIX_TEMPLATE));
+        URI factorySynchUri = UriUtils.buildUri(host, UriUtils.buildUriPath(ExampleService.FACTORY_LINK, SERVICE_URI_SUFFIX_SYNCHRONIZATION));
+        URI factoryUiUri = UriUtils.buildUri(host, UriUtils.buildUriPath(ExampleService.FACTORY_LINK, SERVICE_URI_SUFFIX_UI));
+
+        URI serviceAvailableUri = UriUtils.buildAvailableUri(host, postResult.documentSelfLink);
+        URI serviceStatsUri = UriUtils.buildStatsUri(host, postResult.documentSelfLink);
+        URI serviceConfigUri = UriUtils.buildConfigUri(host, postResult.documentSelfLink);
+        URI serviceSubscriptionUri = UriUtils.buildSubscriptionUri(host, postResult.documentSelfLink);
+        URI serviceTemplateUri = UriUtils.buildUri(host, UriUtils.buildUriPath(postResult.documentSelfLink, SERVICE_URI_SUFFIX_TEMPLATE));
+        URI serviceSynchUri = UriUtils.buildUri(host, UriUtils.buildUriPath(postResult.documentSelfLink, SERVICE_URI_SUFFIX_SYNCHRONIZATION));
+        URI serviceUiUri = UriUtils.buildUri(host, UriUtils.buildUriPath(postResult.documentSelfLink, SERVICE_URI_SUFFIX_UI));
+
+        // check non-authenticated user receives forbidden response
+        FailureResponse failureResponse;
+        Operation uiOpResult;
+
+        // check factory endpoints
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factoryAvailableUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factoryStatsUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factoryConfigUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factorySubscriptionUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factoryTemplateUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factorySynchUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        uiOpResult = sender.sendAndWait(Operation.createGet(factoryUiUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, uiOpResult.getStatusCode());
+
+        // check service endpoints
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceAvailableUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceStatsUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceConfigUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceSubscriptionUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceTemplateUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceSynchUri));
+        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        uiOpResult = sender.sendAndWait(Operation.createGet(serviceUiUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, uiOpResult.getStatusCode());
+
+
+        // check authenticated user does NOT receive forbidden response
+        AuthTestUtils.login(host, exampleUser, examplePass);
+
+        Operation response;
+
+        // check factory endpoints
+        response = sender.sendAndWait(Operation.createGet(factoryAvailableUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(factoryStatsUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(factoryConfigUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(factorySubscriptionUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(factoryTemplateUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factorySynchUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(factoryUiUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+
+        // check service endpoints
+        response = sender.sendAndWait(Operation.createGet(serviceAvailableUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(serviceStatsUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(serviceConfigUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(serviceSubscriptionUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(serviceTemplateUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceSynchUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());
+
+        response = sender.sendAndWait(Operation.createGet(serviceUiUri));
+        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());
+
+    }
+
 }
diff --git a/xenon-common/src/test/java/com/vmware/xenon/common/test/AuthorizationHelper.java b/xenon-common/src/test/java/com/vmware/xenon/common/test/AuthorizationHelper.java
index e847ddb3..162051d6 100644
--- a/xenon-common/src/test/java/com/vmware/xenon/common/test/AuthorizationHelper.java
+++ b/xenon-common/src/test/java/com/vmware/xenon/common/test/AuthorizationHelper.java
@@ -28,10 +28,11 @@ import com.vmware.xenon.common.Operation;
 import com.vmware.xenon.common.Service.Action;
 import com.vmware.xenon.common.ServiceDocument;
 import com.vmware.xenon.common.ServiceHost;
 import com.vmware.xenon.common.UriUtils;
 import com.vmware.xenon.common.Utils;
+import com.vmware.xenon.services.common.ExampleService;
 import com.vmware.xenon.services.common.ExampleService.ExampleServiceState;
 import com.vmware.xenon.services.common.QueryTask;
 import com.vmware.xenon.services.common.QueryTask.Query;
 import com.vmware.xenon.services.common.QueryTask.Query.Builder;
 import com.vmware.xenon.services.common.ResourceGroupService.ResourceGroupState;
@@ -245,10 +246,26 @@ public class AuthorizationHelper {
                         .addFieldClause(
                                 QueryTask.FIELD_NAME_AUTH_PRINCIPAL_LINK,
                                 UriUtils.buildUriPath(ServiceUriPaths.CORE_AUTHZ_USERS, email))
                         .build());
 
+        // Create resource group to allow access on utility paths
+        String statsResourceGroupLink = createResourceGroup(target, "stats-resource-group",
+                Builder.create()
+                        .addFieldClause(
+                                ServiceDocument.FIELD_NAME_SELF_LINK,
+                                ExampleService.FACTORY_LINK + ServiceHost.SERVICE_URI_SUFFIX_STATS)
+                        .build());
+
+        String subscriptionsResourceGroupLink = createResourceGroup(target, "subs-resource-group",
+                Builder.create()
+                        .addFieldClause(
+                                ServiceDocument.FIELD_NAME_SELF_LINK,
+                                ServiceUriPaths.CORE_LOCAL_QUERY_TASKS
+                                        + ServiceHost.SERVICE_URI_SUFFIX_SUBSCRIPTIONS)
+                        .build());
+
         Collection<String> paths = new HashSet<>();
 
         // Create roles tying these together
         String exampleRoleLink = createRole(target, userGroupLink, exampleServiceResourceGroupLink,
                 new HashSet<>(Arrays.asList(Action.GET, Action.POST)));
@@ -259,10 +276,20 @@ public class AuthorizationHelper {
                 new HashSet<>(Collections.singletonList(Action.PATCH))));
 
         // Create role authorizing access to the user's own query tasks
         paths.add(createRole(target, userGroupLink, queryTaskResourceGroupLink,
                 new HashSet<>(Arrays.asList(Action.GET, Action.POST, Action.PATCH, Action.DELETE))));
+
+        // Create role authorizing access to /stats
+        paths.add(createRole(target, userGroupLink, statsResourceGroupLink,
+                new HashSet<>(
+                        Arrays.asList(Action.GET, Action.POST, Action.PATCH, Action.DELETE))));
+
+        // Create role authorizing access to /subscriptions of query tasks
+        paths.add(createRole(target, userGroupLink, subscriptionsResourceGroupLink,
+                new HashSet<>(
+                        Arrays.asList(Action.GET, Action.POST, Action.PATCH, Action.DELETE))));
         return paths;
     }
 
     public String createUserGroup(ServiceHost target, String name, Query q) throws Throwable {
         URI postUserGroupsUri =
diff --git a/xenon-common/src/test/java/com/vmware/xenon/common/test/VerificationHost.java b/xenon-common/src/test/java/com/vmware/xenon/common/test/VerificationHost.java
index 25dc6b2e..f1176223 100644
--- a/xenon-common/src/test/java/com/vmware/xenon/common/test/VerificationHost.java
+++ b/xenon-common/src/test/java/com/vmware/xenon/common/test/VerificationHost.java
@@ -80,10 +80,11 @@ import com.vmware.xenon.common.DeferredResult;
 import com.vmware.xenon.common.NodeSelectorService;
 import com.vmware.xenon.common.NodeSelectorState;
 import com.vmware.xenon.common.Operation;
 import com.vmware.xenon.common.Operation.AuthorizationContext;
 import com.vmware.xenon.common.Operation.CompletionHandler;
+import com.vmware.xenon.common.OperationContext;
 import com.vmware.xenon.common.Service;
 import com.vmware.xenon.common.Service.Action;
 import com.vmware.xenon.common.Service.ServiceOption;
 import com.vmware.xenon.common.ServiceClient;
 import com.vmware.xenon.common.ServiceConfigUpdateRequest;
@@ -1051,11 +1052,19 @@ public class VerificationHost extends ExampleServiceHost {
         factoryUri = UriUtils.buildExpandLinksQueryUri(factoryUri);
         return this.getServiceState(null, ServiceDocumentQueryResult.class, factoryUri);
     }
 
     public Map<String, ServiceStat> getServiceStats(URI serviceUri) {
+        AuthorizationContext ctx = null;
+        if (this.isAuthorizationEnabled()) {
+            ctx = OperationContext.getAuthorizationContext();
+            this.setSystemAuthorizationContext();
+        }
         ServiceStats stats = this.sender.sendStatsGetAndWait(serviceUri);
+        if (this.isAuthorizationEnabled()) {
+            this.setAuthorizationContext(ctx);
+        }
         return stats.entries;
     }
 
     public void doExampleServiceUpdateAndQueryByVersion(URI hostUri, int serviceCount) {
         Consumer<Operation> bodySetter = (o) -> {
diff --git a/xenon-common/src/test/java/com/vmware/xenon/services/common/TestNodeGroupService.java b/xenon-common/src/test/java/com/vmware/xenon/services/common/TestNodeGroupService.java
index ff214001..61e14cd0 100644
--- a/xenon-common/src/test/java/com/vmware/xenon/services/common/TestNodeGroupService.java
+++ b/xenon-common/src/test/java/com/vmware/xenon/services/common/TestNodeGroupService.java
@@ -3438,10 +3438,11 @@ public class TestNodeGroupService {
         this.host.joinNodesAndVerifyConvergence(this.nodeCount);
         this.host.setNodeGroupQuorum(this.nodeCount);
 
         VerificationHost groupHost = this.host.getPeerHost();
 
+        groupHost.setSystemAuthorizationContext();
         // wait for auth related services to be stabilized
         groupHost.waitForReplicatedFactoryServiceAvailable(
                 UriUtils.buildUri(groupHost, UserService.FACTORY_LINK));
         groupHost.waitForReplicatedFactoryServiceAvailable(
                 UriUtils.buildUri(groupHost, UserGroupService.FACTORY_LINK));
@@ -3455,11 +3456,11 @@ public class TestNodeGroupService {
         String barUserLink = UriUtils.buildUriPath(ServiceUriPaths.CORE_AUTHZ_USERS,
                 "bar@vmware.com");
         String bazUserLink = UriUtils.buildUriPath(ServiceUriPaths.CORE_AUTHZ_USERS,
                 "baz@vmware.com");
 
-        groupHost.setSystemAuthorizationContext();
+
 
         // create user, user-group, resource-group, role for foo@vmware.com
         //   user: /core/authz/users/foo@vmware.com
         //   user-group: /core/authz/user-groups/foo-user-group
         //   resource-group:  /core/authz/resource-groups/foo-resource-group
@@ -3665,11 +3666,11 @@ public class TestNodeGroupService {
         for (VerificationHost peer : this.host.getInProcessHostMap().values()) {
             peer.setAuthorizationContext(authContext);
 
             // based on the role created in test, all users have access to ExampleService
             this.host.sendAndWaitExpectSuccess(
-                    Operation.createGet(UriUtils.buildStatsUri(peer, ExampleService.FACTORY_LINK)));
+                    Operation.createGet(UriUtils.buildUri(peer, ExampleService.FACTORY_LINK)));
         }
 
         this.host.waitFor("Timeout waiting for correct auth cache state",
                 () -> checkCacheInAllPeers(authContext.getToken(), true));
     }

Vulnerable code:         op.complete();
        URI usersLink = UriUtils.buildUri(hostUri, UserService.FACTORY_LINK);
        // wait for factory availability
        this.host.waitForReplicatedFactoryServiceAvailable(usersLink);

        this.host.assumeIdentity(userPath);
        return this.host.getServiceStats(managementServiceUri)
        groupHost.setSystemAuthorizationContext();
                    Operation.createGet(UriUtils.buildStatsUri(peer, ExampleService.FACTORY_LINK)));
Fixed code: 
        String suffix = UriUtils.buildUriPath(UriUtils.URI_PATH_CHAR, UriUtils.getLastPathSegment(op.getUri()));

        // allow access to ui endpoint
        if (ServiceHost.SERVICE_URI_SUFFIX_UI.equals(suffix)) {
            op.complete();
            return;
        }

        ServiceDocument doc = new ServiceDocument();
        if (this.parent.getOptions().contains(ServiceOption.FACTORY_ITEM)) {
            doc.documentSelfLink = UriUtils.buildUriPath(UriUtils.getParentPath(this.parent.getSelfLink()), suffix);
        } else {
            doc.documentSelfLink = UriUtils.buildUriPath(this.parent.getSelfLink(), suffix);
        }

        doc.documentKind = Utils.buildKind(this.parent.getStateType());
        if (getHost().isAuthorized(this.parent, doc, op)) {
            op.complete();
            return;
        }

        op.fail(Operation.STATUS_CODE_FORBIDDEN);
        OperationContext.setAuthorizationContext(this.host.getSystemAuthorizationContext());
        OperationContext.setAuthorizationContext(null);
        OperationContext.setAuthorizationContext(this.host.getSystemAuthorizationContext());
        OperationContext.setAuthorizationContext(null);
        // do GET on factory /stats, we should get 403
        Operation statsGet = Operation.createGet(this.host,
                ExampleService.FACTORY_LINK + ServiceHost.SERVICE_URI_SUFFIX_STATS);
        this.host.sendAndWaitExpectFailure(statsGet, Operation.STATUS_CODE_FORBIDDEN);

        // do GET on factory /config, we should get 403
        Operation configGet = Operation.createGet(this.host,
                ExampleService.FACTORY_LINK + ServiceHost.SERVICE_URI_SUFFIX_CONFIG);
        this.host.sendAndWaitExpectFailure(configGet, Operation.STATUS_CODE_FORBIDDEN);

        // do GET on utility suffixes in example child services, we should get 403
        for (URI childUri : exampleServices.keySet()) {
            statsGet = Operation.createGet(this.host,
                    childUri.getPath() + ServiceHost.SERVICE_URI_SUFFIX_STATS);
            this.host.sendAndWaitExpectFailure(statsGet, Operation.STATUS_CODE_FORBIDDEN);
            configGet = Operation.createGet(this.host,
                    childUri.getPath() + ServiceHost.SERVICE_URI_SUFFIX_CONFIG);
            this.host.sendAndWaitExpectFailure(configGet, Operation.STATUS_CODE_FORBIDDEN);
        }

        // do GET on utility suffixes in example child services, we should get 200
        for (URI childUri : exampleServices.keySet()) {
            statsGet = Operation.createGet(this.host,
                    childUri.getPath() + ServiceHost.SERVICE_URI_SUFFIX_STATS);
            statsGet.addRequestHeader(Operation.REQUEST_AUTH_TOKEN_HEADER, authToken);
            this.host.sendAndWaitExpectSuccess(statsGet);
        }

        this.host.setSystemAuthorizationContext();
        this.host.resetSystemAuthorizationContext();

        this.host.assumeIdentity(userPath);


        this.host.setSystemAuthorizationContext();
        this.host.resetSystemAuthorizationContext();
        this.host.setSystemAuthorizationContext();
        this.host.resetSystemAuthorizationContext();
        ServiceStat stats = this.host.getServiceStats(managementServiceUri)
        return stats;

            hostWithAuth.setSystemAuthorizationContext();
            hostWithAuth.resetAuthorizationContext();
import static org.junit.Assert.assertNotEquals;
import static com.vmware.xenon.common.ServiceHost.SERVICE_URI_SUFFIX_SYNCHRONIZATION;
import static com.vmware.xenon.common.ServiceHost.SERVICE_URI_SUFFIX_TEMPLATE;
import static com.vmware.xenon.common.ServiceHost.SERVICE_URI_SUFFIX_UI;

import com.vmware.xenon.common.test.AuthTestUtils;
import com.vmware.xenon.common.test.TestRequestSender;
import com.vmware.xenon.common.test.TestRequestSender.FailureResponse;
import com.vmware.xenon.common.test.VerificationHost;
import com.vmware.xenon.services.common.AuthorizationContextService;
import com.vmware.xenon.services.common.QueryTask.Query;
    @Test
    public void endpointAuthorization() throws Throwable {
        VerificationHost host = VerificationHost.create(0);
        host.setAuthorizationService(new AuthorizationContextService());
        host.setAuthorizationEnabled(true);
        host.setMaintenanceIntervalMicros(TimeUnit.MILLISECONDS.toMicros(100));
        host.start();

        TestRequestSender sender = host.getTestRequestSender();

        host.setSystemAuthorizationContext();
        host.waitForReplicatedFactoryServiceAvailable(UriUtils.buildUri(host, ExampleService.FACTORY_LINK));

        String exampleUser = "example@vmware.com";
        String examplePass = "password";
        TestContext authCtx = host.testCreate(1);
        AuthorizationSetupHelper.create()
                .setHost(host)
                .setUserEmail(exampleUser)
                .setUserPassword(examplePass)
                .setResourceQuery(Query.Builder.create()
                        .addFieldClause(ServiceDocument.FIELD_NAME_KIND, Utils.buildKind(ExampleServiceState.class))
                        .build())
                .setCompletion(authCtx.getCompletion())
                .start();
        authCtx.await();

        // create a sample service
        ExampleServiceState doc = new ExampleServiceState();
        doc.name = "foo";
        doc.documentSelfLink = "foo";

        Operation post = Operation.createPost(host, ExampleService.FACTORY_LINK).setBody(doc);
        ExampleServiceState postResult = sender.sendAndWait(post, ExampleServiceState.class);

        host.resetAuthorizationContext();

        URI factoryAvailableUri = UriUtils.buildAvailableUri(host, ExampleService.FACTORY_LINK);
        URI factoryStatsUri = UriUtils.buildStatsUri(host, ExampleService.FACTORY_LINK);
        URI factoryConfigUri = UriUtils.buildConfigUri(host, ExampleService.FACTORY_LINK);
        URI factorySubscriptionUri = UriUtils.buildSubscriptionUri(host, ExampleService.FACTORY_LINK);
        URI factoryTemplateUri = UriUtils.buildUri(host, UriUtils.buildUriPath(ExampleService.FACTORY_LINK, SERVICE_URI_SUFFIX_TEMPLATE));
        URI factorySynchUri = UriUtils.buildUri(host, UriUtils.buildUriPath(ExampleService.FACTORY_LINK, SERVICE_URI_SUFFIX_SYNCHRONIZATION));
        URI factoryUiUri = UriUtils.buildUri(host, UriUtils.buildUriPath(ExampleService.FACTORY_LINK, SERVICE_URI_SUFFIX_UI));

        URI serviceAvailableUri = UriUtils.buildAvailableUri(host, postResult.documentSelfLink);
        URI serviceStatsUri = UriUtils.buildStatsUri(host, postResult.documentSelfLink);
        URI serviceConfigUri = UriUtils.buildConfigUri(host, postResult.documentSelfLink);
        URI serviceSubscriptionUri = UriUtils.buildSubscriptionUri(host, postResult.documentSelfLink);
        URI serviceTemplateUri = UriUtils.buildUri(host, UriUtils.buildUriPath(postResult.documentSelfLink, SERVICE_URI_SUFFIX_TEMPLATE));
        URI serviceSynchUri = UriUtils.buildUri(host, UriUtils.buildUriPath(postResult.documentSelfLink, SERVICE_URI_SUFFIX_SYNCHRONIZATION));
        URI serviceUiUri = UriUtils.buildUri(host, UriUtils.buildUriPath(postResult.documentSelfLink, SERVICE_URI_SUFFIX_UI));

        // check non-authenticated user receives forbidden response
        FailureResponse failureResponse;
        Operation uiOpResult;

        // check factory endpoints
        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factoryAvailableUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factoryStatsUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factoryConfigUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factorySubscriptionUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factoryTemplateUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factorySynchUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        uiOpResult = sender.sendAndWait(Operation.createGet(factoryUiUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, uiOpResult.getStatusCode());

        // check service endpoints
        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceAvailableUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceStatsUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceConfigUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceSubscriptionUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceTemplateUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceSynchUri));
        assertEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        uiOpResult = sender.sendAndWait(Operation.createGet(serviceUiUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, uiOpResult.getStatusCode());


        // check authenticated user does NOT receive forbidden response
        AuthTestUtils.login(host, exampleUser, examplePass);

        Operation response;

        // check factory endpoints
        response = sender.sendAndWait(Operation.createGet(factoryAvailableUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(factoryStatsUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(factoryConfigUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(factorySubscriptionUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(factoryTemplateUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(factorySynchUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(factoryUiUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());


        // check service endpoints
        response = sender.sendAndWait(Operation.createGet(serviceAvailableUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(serviceStatsUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(serviceConfigUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(serviceSubscriptionUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(serviceTemplateUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

        failureResponse = sender.sendAndWaitFailure(Operation.createGet(serviceSynchUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, failureResponse.op.getStatusCode());

        response = sender.sendAndWait(Operation.createGet(serviceUiUri));
        assertNotEquals(Operation.STATUS_CODE_FORBIDDEN, response.getStatusCode());

    }

import com.vmware.xenon.services.common.ExampleService;
        // Create resource group to allow access on utility paths
        String statsResourceGroupLink = createResourceGroup(target, "stats-resource-group",
                Builder.create()
                        .addFieldClause(
                                ServiceDocument.FIELD_NAME_SELF_LINK,
                                ExampleService.FACTORY_LINK + ServiceHost.SERVICE_URI_SUFFIX_STATS)
                        .build());

        String subscriptionsResourceGroupLink = createResourceGroup(target, "subs-resource-group",
                Builder.create()
                        .addFieldClause(
                                ServiceDocument.FIELD_NAME_SELF_LINK,
                                ServiceUriPaths.CORE_LOCAL_QUERY_TASKS
                                        + ServiceHost.SERVICE_URI_SUFFIX_SUBSCRIPTIONS)
                        .build());


        // Create role authorizing access to /stats
        paths.add(createRole(target, userGroupLink, statsResourceGroupLink,
                new HashSet<>(
                        Arrays.asList(Action.GET, Action.POST, Action.PATCH, Action.DELETE))));

        // Create role authorizing access to /subscriptions of query tasks
        paths.add(createRole(target, userGroupLink, subscriptionsResourceGroupLink,
                new HashSet<>(
                        Arrays.asList(Action.GET, Action.POST, Action.PATCH, Action.DELETE))));
import com.vmware.xenon.common.OperationContext;
        AuthorizationContext ctx = null;
        if (this.isAuthorizationEnabled()) {
            ctx = OperationContext.getAuthorizationContext();
            this.setSystemAuthorizationContext();
        }
        if (this.isAuthorizationEnabled()) {
            this.setAuthorizationContext(ctx);
        }
        groupHost.setSystemAuthorizationContext();

                    Operation.createGet(UriUtils.buildUri(peer, ExampleService.FACTORY_LINK)));