CVE-2017-4952 (published 2018-05-02T14:29Z)

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.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 7.5, HIGH (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-732
cwe_name: Incorrect Permission Assignment for Critical Resource
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.
extended_description: When a resource is given a permission setting that provides access to a wider range of actors than required, it could lead to the exposure of sensitive information, or the modification of that resource by unintended parties. This is especially dangerous when the resource is related to program configuration, execution, or sensitive user data. For example, consider a misconfigured storage account for the cloud that can be read or written by a public or anonymous user.
         

Fix information:
repo_url: https://github.com/vmware/xenon
commit_details: repo_url: https://github.com/vmware/xenon
author: Tadaya Tsuyukubo
author_date: 2017-12-04 12:49:05-08:00
msg: Add auth to UtilityService

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

Issue: VRXEN-5

Change-Id: I52a4b4a42731c244a97f97610dcaddb6837e67fb
repository: repo_url: https://github.com/vmware/xenon
repo_name: vmware-archive/xenon
description: Xenon - Decentralized Control Plane Framework
repo_language: Java
owner: vmware
file_changes: filename: UtilityService.java
change_type: ModificationType.MODIFY
diff: @@ -141,7 +141,29 @@ public class UtilityService implements Service {
 
     @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

programming_language: Java
filename: TestAuthorization.java
change_type: ModificationType.MODIFY
diff: @@ -465,16 +465,20 @@ public class TestAuthorization extends BasicTestCase {
                         .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);
@@ -757,6 +761,16 @@ public class TestAuthorization extends BasicTestCase {
                 }));
         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
@@ -798,9 +812,27 @@ public class TestAuthorization extends BasicTestCase {
         // 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

programming_language: Java
filename: TestExampleServiceHost.java
change_type: ModificationType.MODIFY
diff: @@ -81,10 +81,6 @@ public class TestExampleServiceHost extends BasicReusableHostTestCase {
      * 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();

programming_language: Java
filename: TestServiceHost.java
change_type: ModificationType.MODIFY
diff: @@ -422,9 +422,13 @@ public class TestServiceHost {
         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;
@@ -443,7 +447,10 @@ public class TestServiceHost {
         }
         this.host.testWait(ctx2);
         ctx2.logAfter();
+
+        this.host.setSystemAuthorizationContext();
         ServiceStat rateLimitStatAfter = getRateLimitOpCountStat();
+        this.host.resetSystemAuthorizationContext();
         assertTrue(rateLimitStatAfter.latestValue > rateLimitStatBefore.latestValue);
 
         this.host.setMaintenanceIntervalMicros(
@@ -473,7 +480,9 @@ public class TestServiceHost {
         ctx3.logAfter();
 
         // verify rate limiting did not happen
+        this.host.setSystemAuthorizationContext();
         ServiceStat rateLimitStatExpectSame = getRateLimitOpCountStat();
+        this.host.resetSystemAuthorizationContext();
         assertTrue(rateLimitStatAfter.latestValue == rateLimitStatExpectSame.latestValue);
     }
 
@@ -2225,8 +2234,9 @@ public class TestServiceHost {
 
     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

programming_language: Java
filename: TestSubscriptions.java
change_type: ModificationType.MODIFY
diff: @@ -300,11 +300,14 @@ public class TestSubscriptions extends BasicTestCase {
 
                 }
             };
+
+            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) {

programming_language: Java
filename: TestUtilityService.java
change_type: ModificationType.MODIFY
diff: @@ -14,8 +14,13 @@
 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;
@@ -34,10 +39,16 @@ 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 {
@@ -825,4 +836,158 @@ public class TestUtilityService extends BasicReusableHostTestCase {
         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());
+
+    }
+
 }

programming_language: Java
filename: AuthorizationHelper.java
change_type: ModificationType.MODIFY
diff: @@ -30,6 +30,7 @@ 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;
@@ -247,6 +248,22 @@ public class AuthorizationHelper {
                                 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
@@ -261,6 +278,16 @@ public class AuthorizationHelper {
         // 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;
     }
 

programming_language: Java
filename: VerificationHost.java
change_type: ModificationType.MODIFY
diff: @@ -82,6 +82,7 @@ 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;
@@ -1053,7 +1054,15 @@ public class VerificationHost extends ExampleServiceHost {
     }
 
     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;
     }
 

programming_language: Java
filename: TestNodeGroupService.java
change_type: ModificationType.MODIFY
diff: @@ -3440,6 +3440,7 @@ public class TestNodeGroupService {
 
         VerificationHost groupHost = this.host.getPeerHost();
 
+        groupHost.setSystemAuthorizationContext();
         // wait for auth related services to be stabilized
         groupHost.waitForReplicatedFactoryServiceAvailable(
                 UriUtils.buildUri(groupHost, UserService.FACTORY_LINK));
@@ -3457,7 +3458,7 @@ public class TestNodeGroupService {
         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
@@ -3667,7 +3668,7 @@ public class TestNodeGroupService {
 
             // 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",

programming_language: Java