Skip to content
This repository has been archived by the owner on Nov 9, 2020. It is now read-only.

Commit

Permalink
Add auth to UtilityService
Browse files Browse the repository at this point in the history
Extend auth check to UtiliyService endpoints: stats, config, subscription

Issue: VRXEN-5

Change-Id: I52a4b4a42731c244a97f97610dcaddb6837e67fb
  • Loading branch information
ttddyy authored and Gerrit Code Review committed Feb 13, 2018
1 parent fb560dc commit c23964e
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,29 @@ public UtilityService setParent(Service parent) {

@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -465,16 +465,20 @@ public void guestAuthorization() throws Throwable {
.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);
Expand Down Expand Up @@ -757,6 +761,16 @@ public void statefulServiceAuthorization() throws Throwable {
}));
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
Expand Down Expand Up @@ -798,9 +812,27 @@ public void statefulServiceAuthorization() throws Throwable {
// 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ public void createUsers() throws Throwable {
* 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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,13 @@ private void doRequestRateLimits() throws Throwable {
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;
Expand All @@ -443,7 +447,10 @@ private void doRequestRateLimits() throws Throwable {
}
this.host.testWait(ctx2);
ctx2.logAfter();

this.host.setSystemAuthorizationContext();
ServiceStat rateLimitStatAfter = getRateLimitOpCountStat();
this.host.resetSystemAuthorizationContext();
assertTrue(rateLimitStatAfter.latestValue > rateLimitStatBefore.latestValue);

this.host.setMaintenanceIntervalMicros(
Expand Down Expand Up @@ -473,7 +480,9 @@ private void doRequestRateLimits() throws Throwable {
ctx3.logAfter();

// verify rate limiting did not happen
this.host.setSystemAuthorizationContext();
ServiceStat rateLimitStatExpectSame = getRateLimitOpCountStat();
this.host.resetSystemAuthorizationContext();
assertTrue(rateLimitStatAfter.latestValue == rateLimitStatExpectSame.latestValue);
}

Expand Down Expand Up @@ -2225,8 +2234,9 @@ Operation createMinimalTestServicePatch(String servicePath, TestContext ctx) {

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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,14 @@ public void subscriptionsWithAuth() throws Throwable {

}
};

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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -34,10 +39,16 @@
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 {
Expand Down Expand Up @@ -825,4 +836,158 @@ public void statsKeyOrder() {
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());

}

}
Loading

0 comments on commit c23964e

Please sign in to comment.