You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sv...@apache.org on 2016/02/10 15:08:59 UTC

[1/4] brooklyn-server git commit: REST api: add entitlements for activity streams

Repository: brooklyn-server
Updated Branches:
  refs/heads/master 5c8bb4ebb -> 6693cd0cd


REST api: add entitlements for activity streams

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/4a3ab335
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/4a3ab335
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/4a3ab335

Branch: refs/heads/master
Commit: 4a3ab3355a750ed8540b7a9dbdd18e07ea2bb346
Parents: f0db35f
Author: Aled Sage <al...@gmail.com>
Authored: Wed Feb 10 12:42:31 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Feb 10 12:42:52 2016 +0000

----------------------------------------------------------------------
 .../core/mgmt/entitlement/Entitlements.java     |  26 +++-
 .../rest/resources/ActivityResource.java        |  42 ++++++-
 .../ActivityApiEntitlementsTest.java            | 123 +++++++++++++++++++
 .../AbstractSoftwareProcessStreamsTest.java     |  10 +-
 4 files changed, 187 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4a3ab335/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
index d3f9687..c5b62a4 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
@@ -65,8 +65,9 @@ public class Entitlements {
     public static EntitlementClass<StringAndArgument> MODIFY_CATALOG_ITEM = new BasicEntitlementClassDefinition<StringAndArgument>("catalog.modify", StringAndArgument.class); 
     
     public static EntitlementClass<Entity> SEE_ENTITY = new BasicEntitlementClassDefinition<Entity>("entity.see", Entity.class);
-    public static EntitlementClass<EntityAndItem<String>> SEE_SENSOR = new BasicEntitlementClassDefinition<EntityAndItem<String>>("sensor.see", EntityAndItem. typeToken(String.class));
-    public static EntitlementClass<EntityAndItem<String>> SEE_CONFIG = new BasicEntitlementClassDefinition<EntityAndItem<String>>("config.see", EntityAndItem. typeToken(String.class));
+    public static EntitlementClass<EntityAndItem<String>> SEE_SENSOR = new BasicEntitlementClassDefinition<EntityAndItem<String>>("sensor.see", EntityAndItem.typeToken(String.class));
+    public static EntitlementClass<EntityAndItem<String>> SEE_CONFIG = new BasicEntitlementClassDefinition<EntityAndItem<String>>("config.see", EntityAndItem.typeToken(String.class));
+    public static EntitlementClass<TaskAndItem<String>> SEE_ACTIVITY_STREAMS = new BasicEntitlementClassDefinition<TaskAndItem<String>>("activity.streams.see", TaskAndItem.typeToken(String.class));
     // string is effector name; argument may be a map or a list, depending how the args were supplied
     public static EntitlementClass<EntityAndItem<StringAndArgument>> INVOKE_EFFECTOR = new BasicEntitlementClassDefinition<EntityAndItem<StringAndArgument>>("effector.invoke", EntityAndItem.typeToken(StringAndArgument.class));
     public static EntitlementClass<Entity> MODIFY_ENTITY = new BasicEntitlementClassDefinition<Entity>("entity.modify", Entity.class);
@@ -140,8 +141,12 @@ public class Entitlements {
     protected static class Pair<T1,T2> {
         protected final T1 p1;
         protected final T2 p2;
-        protected Pair(T1 p1, T2 p2) { this.p1 = p1; this.p2 = p2; }
+        protected Pair(T1 p1, T2 p2) {
+            this.p1 = p1;
+            this.p2 = p2;
+        }
     }
+
     public static class EntityAndItem<T> extends Pair<Entity,T> {
         public static <TT> TypeToken<EntityAndItem<TT>> typeToken(Class<TT> type) {
             return new TypeToken<Entitlements.EntityAndItem<TT>>() {
@@ -156,6 +161,20 @@ public class Entitlements {
         }
     }
     
+    public static class TaskAndItem<T> extends Pair<Task<?>,T> {
+        public static <TT> TypeToken<TaskAndItem<TT>> typeToken(Class<TT> type) {
+            return new TypeToken<Entitlements.TaskAndItem<TT>>() {
+                private static final long serialVersionUID = 3103447462213439135L;
+            };
+        }
+        public TaskAndItem(Task<?> task, T item) { super(task, item); }
+        public Task<?> getTask() { return p1; }
+        public T getItem() { return p2; }
+        public static <T> TaskAndItem<T> of(Task<?> task, T item) {
+            return new TaskAndItem<T>(task, item);
+        }
+    }
+    
     public static class StringAndArgument extends Pair<String,Object> {
         public StringAndArgument(String string, Object argument) { super(string, argument); }
         public String getString() { return p1; }
@@ -309,6 +328,7 @@ public class Entitlements {
     public static EntitlementManager readOnly() {
         return FineGrainedEntitlements.anyOf(
             FineGrainedEntitlements.allowing(SEE_ENTITY),
+            FineGrainedEntitlements.allowing(SEE_ACTIVITY_STREAMS),
             FineGrainedEntitlements.seeNonSecretSensors(),
             FineGrainedEntitlements.seeNonSecretConfig()
         );

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4a3ab335/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ActivityResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ActivityResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ActivityResource.java
index 24fea0f..0444188 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ActivityResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ActivityResource.java
@@ -22,10 +22,12 @@ import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.mgmt.HasTaskChildren;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags.WrappedStream;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.rest.api.ActivityApi;
 import org.apache.brooklyn.rest.domain.TaskSummary;
 import org.apache.brooklyn.rest.transform.TaskTransformer;
@@ -39,29 +41,59 @@ public class ActivityResource extends AbstractBrooklynRestResource implements Ac
     @Override
     public TaskSummary get(String taskId) {
         Task<?> t = mgmt().getExecutionManager().getTask(taskId);
-        if (t == null)
+        if (t == null) {
             throw WebResourceUtils.notFound("Cannot find task '%s'", taskId);
+        }
+        checkEntityEntitled(t);
+        
         return TaskTransformer.FROM_TASK.apply(t);
     }
 
     @Override
     public List<TaskSummary> children(String taskId) {
         Task<?> t = mgmt().getExecutionManager().getTask(taskId);
-        if (t == null)
+        if (t == null) {
             throw WebResourceUtils.notFound("Cannot find task '%s'", taskId);
-        if (!(t instanceof HasTaskChildren))
+        }
+        checkEntityEntitled(t);
+        
+        if (!(t instanceof HasTaskChildren)) {
             return Collections.emptyList();
+        }
         return new LinkedList<TaskSummary>(Collections2.transform(Lists.newArrayList(((HasTaskChildren) t).getChildren()),
                 TaskTransformer.FROM_TASK));
     }
 
+    @Override
     public String stream(String taskId, String streamId) {
         Task<?> t = mgmt().getExecutionManager().getTask(taskId);
-        if (t == null)
+        if (t == null) {
             throw WebResourceUtils.notFound("Cannot find task '%s'", taskId);
+        }
+        checkEntityEntitled(t);
+        checkStreamEntitled(t, streamId);
+        
         WrappedStream stream = BrooklynTaskTags.stream(t, streamId);
-        if (stream == null)
+        if (stream == null) {
             throw WebResourceUtils.notFound("Cannot find stream '%s' in task '%s'", streamId, taskId);
+        }
         return stream.streamContents.get();
     }
+    
+    protected void checkEntityEntitled(Task<?> task) {
+        Entity entity = BrooklynTaskTags.getContextEntity(task);
+        if (entity != null && !Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see activity of entity '%s'",
+                    Entitlements.getEntitlementContext().user(), entity);
+        }
+    }
+    
+    protected void checkStreamEntitled(Task<?> task, String streamId) {
+        Entity entity = BrooklynTaskTags.getContextEntity(task);
+        Entitlements.TaskAndItem<String> item = new Entitlements.TaskAndItem<String>(task, streamId);
+        if (entity != null && !Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ACTIVITY_STREAMS, item)) {
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see activity stream of entity '%s'",
+                    Entitlements.getEntitlementContext().user(), entity);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4a3ab335/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/ActivityApiEntitlementsTest.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/ActivityApiEntitlementsTest.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/ActivityApiEntitlementsTest.java
new file mode 100644
index 0000000..bb10197
--- /dev/null
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/ActivityApiEntitlementsTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.brooklyn.rest.entitlement;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementContext;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
+import org.apache.brooklyn.entity.machine.MachineEntity;
+import org.apache.brooklyn.entity.software.base.AbstractSoftwareProcessStreamsTest;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.util.core.task.TaskPredicates;
+import org.apache.brooklyn.util.text.StringPredicates;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+@Test(singleThreaded = true)
+public class ActivityApiEntitlementsTest extends AbstractRestApiEntitlementsTest {
+
+    protected MachineEntity machineEntity;
+    protected Task<?> subTask;
+    protected Map<String, String> streams;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        LocalhostMachineProvisioningLocation loc = app.newLocalhostProvisioningLocation();
+        machineEntity = app.addChild(EntitySpec.create(MachineEntity.class)
+                .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true)
+                .location(loc));
+        machineEntity.start(ImmutableList.<Location>of());
+        
+        machineEntity.execCommand("echo myval");
+        
+        Set<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(mgmt.getExecutionManager(), machineEntity);
+        String taskNameRegex = "ssh: echo myval";
+        
+        streams = Maps.newLinkedHashMap();
+        subTask = AbstractSoftwareProcessStreamsTest.findTaskOrSubTask(tasks, TaskPredicates.displayNameSatisfies(StringPredicates.matchesRegex(taskNameRegex))).get();
+        for (String streamId : ImmutableList.of("stdin", "stdout", "stderr")) {
+            streams.put(streamId, AbstractSoftwareProcessStreamsTest.getStreamOrFail(subTask, streamId));
+        }
+    }
+    
+    @Test(groups = "Integration")
+    public void testGetTask() throws Exception {
+        String path = "/v1/activities/"+subTask.getId();
+        assertPermitted("myRoot", path);
+        assertPermitted("myReadonly", path);
+        assertForbidden("myMinimal", path);
+        assertForbidden("unrecognisedUser", path);
+    }
+    
+    @Test(groups = "Integration")
+    public void testGetStream() throws Exception {
+        String pathPrefix = "/v1/activities/"+subTask.getId()+"/stream/";
+        for (Map.Entry<String, String> entry : streams.entrySet()) {
+            String streamId = entry.getKey();
+            String expectedStream = entry.getValue();
+
+            assertEquals(httpGet("myRoot", pathPrefix+streamId), expectedStream);
+            assertEquals(httpGet("myReadonly", pathPrefix+streamId), expectedStream);
+            assertForbidden("myMinimal", pathPrefix+streamId);
+            assertForbidden("unrecognisedUser", pathPrefix+streamId);
+            
+            StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveStreams(streamId));
+            assertEquals(httpGet("myCustom", pathPrefix+streamId), expectedStream);
+            
+            StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveStreams("differentStreamId"));
+            assertForbidden("myCustom", pathPrefix+streamId);
+        }
+    }
+    
+    public static class SeeSelectiveStreams implements EntitlementManager {
+        private final String regex;
+        
+        public SeeSelectiveStreams(String regex) {
+            this.regex = regex;
+        }
+        @Override 
+        @SuppressWarnings("unchecked")
+        public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
+            String type = entitlementClass.entitlementClassIdentifier();
+            if (Entitlements.SEE_ACTIVITY_STREAMS.entitlementClassIdentifier().equals(type)) {
+                Entitlements.TaskAndItem<String> pair = (Entitlements.TaskAndItem<String>) entitlementClassArgument;
+                return pair.getItem().matches(regex);
+            } else {
+                return true;
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4a3ab335/software/base/src/test/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessStreamsTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessStreamsTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessStreamsTest.java
index cfc4826..4197551 100644
--- a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessStreamsTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessStreamsTest.java
@@ -59,7 +59,7 @@ public abstract class AbstractSoftwareProcessStreamsTest extends BrooklynAppLive
         return checkNotNull(stream.streamContents.get(), "Contents null: "+msg);
     }
 
-    protected Optional<Task<?>> findTaskOrSubTask(Iterable<? extends Task<?>> tasks, Predicate<? super Task<?>> matcher) {
+    public static Optional<Task<?>> findTaskOrSubTask(Iterable<? extends Task<?>> tasks, Predicate<? super Task<?>> matcher) {
         List<String> taskNames = Lists.newArrayList();
         Optional<Task<?>> result = findTaskOrSubTaskImpl(tasks, matcher, taskNames);
         if (!result.isPresent() && log.isDebugEnabled()) {
@@ -68,13 +68,11 @@ public abstract class AbstractSoftwareProcessStreamsTest extends BrooklynAppLive
         return result;
     }
 
-    protected Optional<Task<?>> findTaskOrSubTaskImpl(Iterable<? extends Task<?>> tasks, Predicate<? super Task<?>> matcher, List<String> taskNames) {
+    public static Optional<Task<?>> findTaskOrSubTaskImpl(Iterable<? extends Task<?>> tasks, Predicate<? super Task<?>> matcher, List<String> taskNames) {
         for (Task<?> task : tasks) {
             if (matcher.apply(task)) return Optional.<Task<?>>of(task);
 
-            if (!(task instanceof HasTaskChildren)) {
-                return Optional.absent();
-            } else {
+            if (task instanceof HasTaskChildren) {
                 Optional<Task<?>> subResult = findTaskOrSubTask(((HasTaskChildren) task).getChildren(), matcher);
                 if (subResult.isPresent()) return subResult;
             }
@@ -90,7 +88,7 @@ public abstract class AbstractSoftwareProcessStreamsTest extends BrooklynAppLive
             String taskNameRegex = entry.getKey();
             String echoed = entry.getValue();
 
-            Task<?> subTask = findTaskOrSubTask(tasks, TaskPredicates.displayNameMatches(StringPredicates.matchesRegex(taskNameRegex))).get();
+            Task<?> subTask = findTaskOrSubTask(tasks, TaskPredicates.displayNameSatisfies(StringPredicates.matchesRegex(taskNameRegex))).get();
 
             String stdin = getStreamOrFail(subTask, BrooklynTaskTags.STREAM_STDIN);
             String stdout = getStreamOrFail(subTask, BrooklynTaskTags.STREAM_STDOUT);


[4/4] brooklyn-server git commit: Closes #16

Posted by sv...@apache.org.
Closes #16

Add entitlements checks for sensor/config lookup


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/6693cd0c
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/6693cd0c
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/6693cd0c

Branch: refs/heads/master
Commit: 6693cd0cd7a1f26dd97a52095674ed3a0ff97f74
Parents: 5c8bb4e 4a3ab33
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Wed Feb 10 16:08:24 2016 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Wed Feb 10 16:08:24 2016 +0200

----------------------------------------------------------------------
 .../core/mgmt/entitlement/Entitlements.java     |  42 ++++++-
 .../mgmt/entitlement/EntityEntitlementTest.java |   4 +
 .../rest/resources/ActivityResource.java        |  42 ++++++-
 .../rest/resources/ApplicationResource.java     |   8 +-
 .../rest/resources/CatalogResource.java         |  32 ++---
 .../rest/resources/EffectorResource.java        |   2 +-
 .../rest/resources/EntityConfigResource.java    |  77 ++++++++----
 .../brooklyn/rest/resources/EntityResource.java |   4 +-
 .../rest/resources/PolicyConfigResource.java    |   2 +-
 .../brooklyn/rest/resources/SensorResource.java |  59 +++++++--
 .../brooklyn/rest/resources/ServerResource.java |  16 +--
 .../rest/util/BrooklynRestResourceUtils.java    |   6 +-
 .../AbstractRestApiEntitlementsTest.java        | 111 +++++++++++++++++
 .../ActivityApiEntitlementsTest.java            | 123 +++++++++++++++++++
 .../AuthenticateAnyoneSecurityProvider.java     |  41 +++++++
 .../EntityConfigApiEntitlementsTest.java        | 103 ++++++++++++++++
 .../entitlement/SensorApiEntitlementsTest.java  | 108 ++++++++++++++++
 .../entitlement/ServerApiEntitlementsTest.java  |  34 +++++
 .../StaticDelegatingEntitlementManager.java     |  37 ++++++
 .../AbstractSoftwareProcessStreamsTest.java     |  10 +-
 20 files changed, 779 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/6693cd0c/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --cc rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index d9c38b6,351f65a..97ed1d9
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@@ -241,9 -280,9 +241,9 @@@ public class ApplicationResource extend
  
          log.debug("Creating app from yaml:\n{}", yaml);
          EntitySpec<? extends Application> spec = createEntitySpecForApplication(yaml);
 -        
 +
          if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.DEPLOY_APPLICATION, spec)) {
-             throw WebResourceUtils.unauthorized("User '%s' is not authorized to start application %s",
+             throw WebResourceUtils.forbidden("User '%s' is not authorized to start application %s",
                  Entitlements.getEntitlementContext().user(), yaml);
          }
  
@@@ -322,9 -361,9 +322,9 @@@
      @Override
      public Response delete(String application) {
          Application app = brooklyn().getApplication(application);
 -        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, Entitlements.EntityAndItem.of(app, 
 +        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, Entitlements.EntityAndItem.of(app,
              StringAndArgument.of(Entitlements.LifecycleEffectors.DELETE, null)))) {
-             throw WebResourceUtils.unauthorized("User '%s' is not authorized to delete application %s",
+             throw WebResourceUtils.forbidden("User '%s' is not authorized to delete application %s",
                  Entitlements.getEntitlementContext().user(), app);
          }
          Task<?> t = brooklyn().destroy(app);


[2/4] brooklyn-server git commit: REST api: forbidden instead of unauthorized

Posted by sv...@apache.org.
REST api: forbidden instead of unauthorized

When entitlement check fails, return 403 instead of 401.

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/f0db35f1
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/f0db35f1
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/f0db35f1

Branch: refs/heads/master
Commit: f0db35f1647e7cb5a89753ec8b2c9e2ceb6dd998
Parents: a055717
Author: Aled Sage <al...@gmail.com>
Authored: Wed Feb 10 10:39:00 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Feb 10 12:42:52 2016 +0000

----------------------------------------------------------------------
 .../rest/resources/ApplicationResource.java     |  8 ++---
 .../rest/resources/CatalogResource.java         | 32 ++++++++++----------
 .../rest/resources/EffectorResource.java        |  2 +-
 .../rest/resources/EntityConfigResource.java    | 12 ++++----
 .../brooklyn/rest/resources/EntityResource.java |  4 +--
 .../rest/resources/PolicyConfigResource.java    |  2 +-
 .../brooklyn/rest/resources/SensorResource.java | 14 ++++-----
 .../brooklyn/rest/resources/ServerResource.java | 16 +++++-----
 .../rest/util/BrooklynRestResourceUtils.java    |  6 ++--
 .../AbstractRestApiEntitlementsTest.java        |  2 +-
 10 files changed, 49 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index 22a4502..351f65a 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -245,7 +245,7 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements
     /** @deprecated since 0.7.0 see #create */ @Deprecated
     protected Response createFromAppSpec(ApplicationSpec applicationSpec) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.DEPLOY_APPLICATION, applicationSpec)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to start application %s",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to start application %s",
                 Entitlements.getEntitlementContext().user(), applicationSpec);
         }
 
@@ -282,7 +282,7 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements
         EntitySpec<? extends Application> spec = createEntitySpecForApplication(yaml);
         
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.DEPLOY_APPLICATION, spec)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to start application %s",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to start application %s",
                 Entitlements.getEntitlementContext().user(), yaml);
         }
 
@@ -300,7 +300,7 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements
                     EntityAndItem.of(app, StringAndArgument.of(Startable.START.getName(), null)));
 
             if (!isEntitled) {
-                throw WebResourceUtils.unauthorized("User '%s' is not authorized to start application %s",
+                throw WebResourceUtils.forbidden("User '%s' is not authorized to start application %s",
                     Entitlements.getEntitlementContext().user(), spec.getType());
             }
 
@@ -363,7 +363,7 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements
         Application app = brooklyn().getApplication(application);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, Entitlements.EntityAndItem.of(app, 
             StringAndArgument.of(Entitlements.LifecycleEffectors.DELETE, null)))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to delete application %s",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to delete application %s",
                 Entitlements.getEntitlementContext().user(), app);
         }
         Task<?> t = brooklyn().destroy(app);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 82bac22..a26f1a1 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -105,7 +105,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public Response create(String yaml) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.ADD_CATALOG_ITEM, yaml)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to add catalog item",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to add catalog item",
                 Entitlements.getEntitlementContext().user());
         }
         
@@ -139,7 +139,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     public Response resetXml(String xml, boolean ignoreErrors) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_CATALOG_ITEM, null) ||
             !Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.ADD_CATALOG_ITEM, null)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify catalog",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify catalog",
                 Entitlements.getEntitlementContext().user());
         }
 
@@ -151,7 +151,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Deprecated
     public void deleteEntity(String entityId) throws Exception {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_CATALOG_ITEM, StringAndArgument.of(entityId, "delete"))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify catalog",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify catalog",
                 Entitlements.getEntitlementContext().user());
         }
         try {
@@ -180,7 +180,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public void deleteEntity(String symbolicName, String version) throws Exception {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_CATALOG_ITEM, StringAndArgument.of(symbolicName+(Strings.isBlank(version) ? "" : ":"+version), "delete"))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify catalog",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify catalog",
                 Entitlements.getEntitlementContext().user());
         }
         
@@ -197,7 +197,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public void deletePolicy(String policyId, String version) throws Exception {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_CATALOG_ITEM, StringAndArgument.of(policyId+(Strings.isBlank(version) ? "" : ":"+version), "delete"))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify catalog",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify catalog",
                 Entitlements.getEntitlementContext().user());
         }
         
@@ -214,7 +214,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public void deleteLocation(String locationId, String version) throws Exception {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_CATALOG_ITEM, StringAndArgument.of(locationId+(Strings.isBlank(version) ? "" : ":"+version), "delete"))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify catalog",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify catalog",
                 Entitlements.getEntitlementContext().user());
         }
         
@@ -253,7 +253,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Deprecated
     public CatalogEntitySummary getEntity(String entityId) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, entityId)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see catalog entry",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see catalog entry",
                 Entitlements.getEntitlementContext().user());
         }
 
@@ -270,7 +270,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public CatalogEntitySummary getEntity(String symbolicName, String version) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, symbolicName+(Strings.isBlank(version)?"":":"+version))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see catalog entry",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see catalog entry",
                 Entitlements.getEntitlementContext().user());
         }
 
@@ -312,7 +312,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Deprecated
     public CatalogPolicySummary getPolicy(String policyId) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, policyId)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see catalog entry",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see catalog entry",
                 Entitlements.getEntitlementContext().user());
         }
 
@@ -329,7 +329,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public CatalogPolicySummary getPolicy(String policyId, String version) throws Exception {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, policyId+(Strings.isBlank(version)?"":":"+version))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see catalog entry",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see catalog entry",
                 Entitlements.getEntitlementContext().user());
         }
 
@@ -358,7 +358,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Deprecated
     public CatalogLocationSummary getLocation(String locationId) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, locationId)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see catalog entry",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see catalog entry",
                 Entitlements.getEntitlementContext().user());
         }
 
@@ -375,7 +375,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public CatalogLocationSummary getLocation(String locationId, String version) throws Exception {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, locationId+(Strings.isBlank(version)?"":":"+version))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see catalog entry",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see catalog entry",
                 Entitlements.getEntitlementContext().user());
         }
 
@@ -414,7 +414,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Deprecated
     public Response getIcon(String itemId) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, itemId)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see catalog entry",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see catalog entry",
                 Entitlements.getEntitlementContext().user());
         }
 
@@ -424,7 +424,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public Response getIcon(String itemId, String version) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, itemId+(Strings.isBlank(version)?"":":"+version))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see catalog entry",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see catalog entry",
                 Entitlements.getEntitlementContext().user());
         }
         
@@ -442,7 +442,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public void setDeprecated(String itemId, boolean deprecated) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_CATALOG_ITEM, StringAndArgument.of(itemId, "deprecated"))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify catalog",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify catalog",
                     Entitlements.getEntitlementContext().user());
         }
         CatalogUtils.setDeprecated(mgmt(), itemId, deprecated);
@@ -452,7 +452,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     @Override
     public void setDisabled(String itemId, boolean disabled) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_CATALOG_ITEM, StringAndArgument.of(itemId, "disabled"))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify catalog",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify catalog",
                     Entitlements.getEntitlementContext().user());
         }
         CatalogUtils.setDisabled(mgmt(), itemId, disabled);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
index 4110d47..710e2de 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
@@ -86,7 +86,7 @@ public class EffectorResource extends AbstractBrooklynRestResource implements Ef
             throw WebResourceUtils.notFound("Entity '%s' has no effector with name '%s'", entityToken, effectorName);
         } else if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.INVOKE_EFFECTOR,
                 Entitlements.EntityAndItem.of(entity, StringAndArgument.of(effector.get().getName(), null)))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to invoke effector %s on entity %s",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to invoke effector %s on entity %s",
                     Entitlements.getEntitlementContext().user(), effector.get().getName(), entity);
         }
         log.info("REST invocation of " + entity + "." + effector.get() + " " + parameters);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
index e6dd315..7aaa3f7 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
@@ -56,7 +56,7 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
     public List<EntityConfigSummary> list(final String application, final String entityToken) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
 
@@ -84,7 +84,7 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
         // TODO: add test
         Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
 
@@ -141,11 +141,11 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
         ConfigKey<?> ck = findConfig(entity, configKeyName);
         
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CONFIG, new EntityAndItem<String>(entity, ck.getName()))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s' config '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s' config '%s'",
                     Entitlements.getEntitlementContext().user(), entity, ck.getName());
         }
         
@@ -165,7 +165,7 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
     public void setFromMap(String application, String entityToken, Boolean recurse, Map newValues) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
 
@@ -190,7 +190,7 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
     public void set(String application, String entityToken, String configName, Boolean recurse, Object newValue) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
index 9575236..c4df6d4 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
@@ -90,7 +90,7 @@ public class EntityResource extends AbstractBrooklynRestResource implements Enti
         if (Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
             return EntityTransformer.entitySummary(entity);
         }
-        throw WebResourceUtils.unauthorized("User '%s' is not authorized to get entity '%s'",
+        throw WebResourceUtils.forbidden("User '%s' is not authorized to get entity '%s'",
                 Entitlements.getEntitlementContext().user(), entity);
     }
 
@@ -113,7 +113,7 @@ public class EntityResource extends AbstractBrooklynRestResource implements Enti
     public Response addChildren(String applicationToken, String entityToken, Boolean start, String timeoutS, String yaml) {
         final Entity parent = brooklyn().getEntity(applicationToken, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, parent)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'",
                     Entitlements.getEntitlementContext().user(), entityToken);
         }
         CreationResult<List<Entity>, List<String>> added = EntityManagementUtils.addChildren(parent, yaml, start)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
index fe28576..fbb13a7 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
@@ -89,7 +89,7 @@ public class PolicyConfigResource extends AbstractBrooklynRestResource implement
     public Response set(String application, String entityToken, String policyToken, String configKeyName, Object value) {
         Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
index edb5c7f..2f03196 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
@@ -53,7 +53,7 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
     public List<SensorSummary> list(final String application, final String entityToken) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
 
@@ -76,7 +76,7 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
     public Map<String, Object> batchSensorRead(final String application, final String entityToken, final Boolean raw) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
 
@@ -104,11 +104,11 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
         AttributeSensor<?> sensor = findSensor(entity, sensorName);
         
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s'",
                     Entitlements.getEntitlementContext().user(), entity);
         }
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_SENSOR, new EntityAndItem<String>(entity, sensor.getName()))) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s' sensor '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s' sensor '%s'",
                     Entitlements.getEntitlementContext().user(), entity, sensor.getName());
         }
         
@@ -137,7 +137,7 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
     public void setFromMap(String application, String entityToken, Map newValues) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'",
                 Entitlements.getEntitlementContext().user(), entity);
         }
 
@@ -157,7 +157,7 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
     public void set(String application, String entityToken, String sensorName, Object newValue) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'",
                 Entitlements.getEntitlementContext().user(), entity);
         }
         
@@ -171,7 +171,7 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
     public void delete(String application, String entityToken, String sensorName) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'",
                 Entitlements.getEntitlementContext().user(), entity);
         }
         

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
index c029bd3..426870d 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
@@ -108,7 +108,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
             Long delayMillis) {
         
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ALL_SERVER_INFO, null))
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
+            throw WebResourceUtils.forbidden("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
         
         log.info("REST call to shutdown server, stopAppsFirst="+stopAppsFirst+", delayForHttpReturn="+shutdownTimeoutRaw);
 
@@ -311,7 +311,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
     @Override
     public VersionSummary getVersion() {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS, null))
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
+            throw WebResourceUtils.forbidden("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
         
         // TODO
         // * "build-metadata.properties" is probably the wrong name
@@ -338,7 +338,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
     @Override
     public boolean isUp() {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS, null))
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
+            throw WebResourceUtils.forbidden("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
 
         Maybe<ManagementContext> mm = mgmtMaybe();
         return !mm.isAbsent() && mm.get().isStartupComplete() && mm.get().isRunning();
@@ -347,7 +347,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
     @Override
     public boolean isShuttingDown() {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS, null))
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
+            throw WebResourceUtils.forbidden("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
         Maybe<ManagementContext> mm = mgmtMaybe();
         return !mm.isAbsent() && mm.get().isStartupComplete() && !mm.get().isRunning();
     }
@@ -376,7 +376,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
     @Override
     public String getConfig(String configKey) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ALL_SERVER_INFO, null)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
+            throw WebResourceUtils.forbidden("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
         }
         ConfigKey<String> config = ConfigKeys.newStringConfigKey(configKey);
         return mgmt().getConfig().getConfig(config);
@@ -391,7 +391,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
     @Override
     public ManagementNodeState getHighAvailabilityNodeState() {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS, null))
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
+            throw WebResourceUtils.forbidden("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
         
         Maybe<ManagementContext> mm = mgmtMaybe();
         if (mm.isAbsent()) return ManagementNodeState.INITIALIZING;
@@ -430,7 +430,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
     @Override
     public HighAvailabilitySummary getHighAvailabilityPlaneStates() {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS, null))
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
+            throw WebResourceUtils.forbidden("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
         ManagementPlaneSyncRecord memento = mgmt().getHighAvailabilityManager().getLastManagementPlaneSyncRecord();
         if (memento==null) memento = mgmt().getHighAvailabilityManager().loadManagementPlaneSyncRecord(true);
         if (memento==null) return null;
@@ -460,7 +460,7 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv
     
     protected Response exportPersistenceData(MementoCopyMode preferredOrigin) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ALL_SERVER_INFO, null))
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
+            throw WebResourceUtils.forbidden("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user());
 
         File dir = null;
         try {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
index 1b9aa77..829b7cb 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -307,7 +307,7 @@ public class BrooklynRestResourceUtils {
         log.debug("REST creating application instance for {}", spec);
         
         if (!Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.DEPLOY_APPLICATION, spec)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to deploy application %s",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to deploy application %s",
                 Entitlements.getEntitlementContext().user(), spec);
         }
         
@@ -327,7 +327,7 @@ public class BrooklynRestResourceUtils {
         }
         
         if (!Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, null)) {
-            throw WebResourceUtils.unauthorized("User '%s' is not authorized to create application from applicationSpec %s",
+            throw WebResourceUtils.forbidden("User '%s' is not authorized to create application from applicationSpec %s",
                 Entitlements.getEntitlementContext().user(), spec);
         }
 
@@ -525,7 +525,7 @@ public class BrooklynRestResourceUtils {
                         }
                     });
         }
-        throw WebResourceUtils.unauthorized("User '%s' is not authorized to expunge entity %s",
+        throw WebResourceUtils.forbidden("User '%s' is not authorized to expunge entity %s",
                     Entitlements.getEntitlementContext().user(), entity);
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f0db35f1/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java
index c851b48..73449ea 100644
--- a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java
@@ -101,7 +101,7 @@ public abstract class AbstractRestApiEntitlementsTest extends BrooklynRestApiLau
 
     protected void assertForbidden(String user, String path) throws Exception {
         HttpToolResponse response = HttpTool.httpGet(newClient(user), URI.create(getBaseUri()).resolve(path), ImmutableMap.<String, String>of());
-        assertEquals(response.getResponseCode(), 401, "code="+response.getResponseCode()+"; reason="+response.getReasonPhrase()+"; content="+response.getContentAsString());
+        assertEquals(response.getResponseCode(), 403, "code="+response.getResponseCode()+"; reason="+response.getReasonPhrase()+"; content="+response.getContentAsString());
     }
 
     protected void assert404(String user, String path) throws Exception {


[3/4] brooklyn-server git commit: Add entitlements checks for sensor/config lookup

Posted by sv...@apache.org.
Add entitlements checks for sensor/config lookup


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/a0557178
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/a0557178
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/a0557178

Branch: refs/heads/master
Commit: a0557178d92efbad7b8f176b84b3f4d56da804d3
Parents: bb8980a
Author: Aled Sage <al...@gmail.com>
Authored: Tue Feb 9 17:27:40 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Feb 10 12:42:52 2016 +0000

----------------------------------------------------------------------
 .../core/mgmt/entitlement/Entitlements.java     |  18 ++-
 .../mgmt/entitlement/EntityEntitlementTest.java |   4 +
 .../rest/resources/EntityConfigResource.java    |  73 ++++++++----
 .../brooklyn/rest/resources/SensorResource.java |  55 +++++++--
 .../AbstractRestApiEntitlementsTest.java        | 111 +++++++++++++++++++
 .../AuthenticateAnyoneSecurityProvider.java     |  41 +++++++
 .../EntityConfigApiEntitlementsTest.java        | 103 +++++++++++++++++
 .../entitlement/SensorApiEntitlementsTest.java  | 108 ++++++++++++++++++
 .../entitlement/ServerApiEntitlementsTest.java  |  34 ++++++
 .../StaticDelegatingEntitlementManager.java     |  37 +++++++
 10 files changed, 554 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
index 6c281fc..d3f9687 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
@@ -66,6 +66,7 @@ public class Entitlements {
     
     public static EntitlementClass<Entity> SEE_ENTITY = new BasicEntitlementClassDefinition<Entity>("entity.see", Entity.class);
     public static EntitlementClass<EntityAndItem<String>> SEE_SENSOR = new BasicEntitlementClassDefinition<EntityAndItem<String>>("sensor.see", EntityAndItem. typeToken(String.class));
+    public static EntitlementClass<EntityAndItem<String>> SEE_CONFIG = new BasicEntitlementClassDefinition<EntityAndItem<String>>("config.see", EntityAndItem. typeToken(String.class));
     // string is effector name; argument may be a map or a list, depending how the args were supplied
     public static EntitlementClass<EntityAndItem<StringAndArgument>> INVOKE_EFFECTOR = new BasicEntitlementClassDefinition<EntityAndItem<StringAndArgument>>("effector.invoke", EntityAndItem.typeToken(StringAndArgument.class));
     public static EntitlementClass<Entity> MODIFY_ENTITY = new BasicEntitlementClassDefinition<Entity>("entity.modify", Entity.class);
@@ -274,6 +275,7 @@ public class Entitlements {
                 return "Entitlements.allowing(" + permission + " -> " + test + ")";
             }
         }
+        
         public static EntitlementManager seeNonSecretSensors() {
             return allowing(SEE_SENSOR, new Predicate<EntityAndItem<String>>() {
                 @Override
@@ -288,13 +290,27 @@ public class Entitlements {
             });
         }
         
+        public static EntitlementManager seeNonSecretConfig() {
+            return allowing(SEE_CONFIG, new Predicate<EntityAndItem<String>>() {
+                @Override
+                public boolean apply(EntityAndItem<String> input) {
+                    if (input == null) return false;
+                    return !Sanitizer.IS_SECRET_PREDICATE.apply(input.getItem());
+                }
+                @Override
+                public String toString() {
+                    return "Predicates.nonSecret";
+                }
+            });
+        }
     }
     
     /** allow read-only */
     public static EntitlementManager readOnly() {
         return FineGrainedEntitlements.anyOf(
             FineGrainedEntitlements.allowing(SEE_ENTITY),
-            FineGrainedEntitlements.seeNonSecretSensors()
+            FineGrainedEntitlements.seeNonSecretSensors(),
+            FineGrainedEntitlements.seeNonSecretConfig()
         );
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/core/src/test/java/org/apache/brooklyn/core/mgmt/entitlement/EntityEntitlementTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/entitlement/EntityEntitlementTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/entitlement/EntityEntitlementTest.java
index 933d117..6a0a8d0 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/entitlement/EntityEntitlementTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/entitlement/EntityEntitlementTest.java
@@ -70,6 +70,7 @@ public class EntityEntitlementTest {
         Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
         Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
         Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+        Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_CONFIG, EntityAndItem.of(app, "any-config")));
         // and can invoke methods, without any user/login registered
         confirmEffectorEntitlement(true);
         confirmSensorEntitlement(true);
@@ -83,6 +84,7 @@ public class EntityEntitlementTest {
         Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
         Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
         Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+        Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_CONFIG, EntityAndItem.of(app, "any-config")));
         
         confirmEffectorEntitlement(true);
         confirmSensorEntitlement(true);
@@ -121,6 +123,7 @@ public class EntityEntitlementTest {
         Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
         Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
         Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+        Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_CONFIG, EntityAndItem.of(app, "any-config")));
         
         confirmEffectorEntitlement(false);
         confirmSensorEntitlement(true);
@@ -134,6 +137,7 @@ public class EntityEntitlementTest {
         Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
         Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
         Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+        Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_CONFIG, EntityAndItem.of(app, "any-config")));
         
         confirmEffectorEntitlement(false);
         confirmSensorEntitlement(false);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
index a6d3b8e..e6dd315 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
@@ -18,18 +18,18 @@
  */
 package org.apache.brooklyn.rest.resources;
 
-import static com.google.common.collect.Iterables.transform;
-
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
 
 import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.BasicConfigKey;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.EntityAndItem;
 import org.apache.brooklyn.rest.api.EntityConfigApi;
 import org.apache.brooklyn.rest.domain.EntityConfigSummary;
 import org.apache.brooklyn.rest.filter.HaHotStateRequired;
@@ -43,7 +43,6 @@ import org.apache.brooklyn.util.time.Duration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Function;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -56,15 +55,26 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
     @Override
     public List<EntityConfigSummary> list(final String application, final String entityToken) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
-        // TODO merge with keys which have values
-        return Lists.newArrayList(transform(
-                entity.getEntityType().getConfigKeys(),
-                new Function<ConfigKey<?>, EntityConfigSummary>() {
-                    @Override
-                    public EntityConfigSummary apply(ConfigKey<?> config) {
-                        return EntityTransformer.entityConfigSummary(entity, config);
-                    }
-                }));
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+                    Entitlements.getEntitlementContext().user(), entity);
+        }
+
+        // TODO merge with keys which have values:
+        //      ((EntityInternal) entity).config().getBag().getAllConfigAsConfigKeyMap();
+        List<EntityConfigSummary> result = Lists.newArrayList();
+        
+        for (ConfigKey<?> key : entity.getEntityType().getConfigKeys()) {
+            // Exclude config that user is not allowed to see
+            if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CONFIG, new EntityAndItem<String>(entity, key.getName()))) {
+                LOG.trace("User {} not authorized to see config {} of entity {}; excluding from ConfigKey list results", 
+                        new Object[] {Entitlements.getEntitlementContext().user(), key.getName(), entity});
+                continue;
+            }
+            result.add(EntityTransformer.entityConfigSummary(entity, key));
+        }
+        
+        return result;
     }
 
     // TODO support parameters  ?show=value,summary&name=xxx &format={string,json,xml}
@@ -73,16 +83,23 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
     public Map<String, Object> batchConfigRead(String application, String entityToken, Boolean raw) {
         // TODO: add test
         Entity entity = brooklyn().getEntity(application, entityToken);
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+                    Entitlements.getEntitlementContext().user(), entity);
+        }
+
         // wrap in a task for better runtime view
-        return Entities.submit(entity, Tasks.<Map<String,Object>>builder().displayName("REST API batch config read").body(new BatchConfigRead(this, entity, raw)).build()).getUnchecked();
+        return Entities.submit(entity, Tasks.<Map<String,Object>>builder().displayName("REST API batch config read").body(new BatchConfigRead(mgmt(), this, entity, raw)).build()).getUnchecked();
     }
     
     private static class BatchConfigRead implements Callable<Map<String,Object>> {
-        private EntityConfigResource resource;
-        private Entity entity;
-        private Boolean raw;
+        private final ManagementContext mgmt;
+        private final EntityConfigResource resource;
+        private final Entity entity;
+        private final Boolean raw;
 
-        public BatchConfigRead(EntityConfigResource resource, Entity entity, Boolean raw) {
+        public BatchConfigRead(ManagementContext mgmt, EntityConfigResource resource, Entity entity, Boolean raw) {
+            this.mgmt = mgmt;
             this.resource = resource;
             this.entity = entity;
             this.raw = raw;
@@ -93,9 +110,17 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
             Map<ConfigKey<?>, ?> source = ((EntityInternal) entity).config().getBag().getAllConfigAsConfigKeyMap();
             Map<String, Object> result = Maps.newLinkedHashMap();
             for (Map.Entry<ConfigKey<?>, ?> ek : source.entrySet()) {
+                ConfigKey<?> key = ek.getKey();
                 Object value = ek.getValue();
-                result.put(ek.getKey().getName(), 
-                    resource.resolving(value).preferJson(true).asJerseyOutermostReturnValue(false).raw(raw).context(entity).timeout(Duration.ZERO).renderAs(ek.getKey()).resolve());
+                
+                // Exclude config that user is not allowed to see
+                if (!Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_CONFIG, new EntityAndItem<String>(entity, ek.getKey().getName()))) {
+                    LOG.trace("User {} not authorized to see sensor {} of entity {}; excluding from current-state results", 
+                            new Object[] {Entitlements.getEntitlementContext().user(), ek.getKey().getName(), entity});
+                    continue;
+                }
+                result.put(key.getName(), 
+                    resource.resolving(value).preferJson(true).asJerseyOutermostReturnValue(false).raw(raw).context(entity).timeout(Duration.ZERO).renderAs(key).resolve());
             }
             return result;
         }
@@ -114,6 +139,16 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
     public Object get(boolean preferJson, String application, String entityToken, String configKeyName, Boolean raw) {
         Entity entity = brooklyn().getEntity(application, entityToken);
         ConfigKey<?> ck = findConfig(entity, configKeyName);
+        
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+                    Entitlements.getEntitlementContext().user(), entity);
+        }
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_CONFIG, new EntityAndItem<String>(entity, ck.getName()))) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s' config '%s'",
+                    Entitlements.getEntitlementContext().user(), entity, ck.getName());
+        }
+        
         Object value = ((EntityInternal)entity).config().getRaw(ck).orNull();
         return resolving(value).preferJson(preferJson).asJerseyOutermostReturnValue(true).raw(raw).context(entity).timeout(ValueResolver.PRETTY_QUICK_WAIT).renderAs(ck).resolve();
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
index 303c0df..edb5c7f 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
@@ -19,7 +19,6 @@
 package org.apache.brooklyn.rest.resources;
 
 import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
 
 import java.util.List;
 import java.util.Map;
@@ -29,6 +28,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Sensor;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.EntityAndItem;
 import org.apache.brooklyn.core.sensor.BasicAttributeSensor;
 import org.apache.brooklyn.rest.api.SensorApi;
 import org.apache.brooklyn.rest.domain.SensorSummary;
@@ -41,7 +41,6 @@ import org.apache.brooklyn.util.time.Duration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Function;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
@@ -50,28 +49,49 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
 
     private static final Logger log = LoggerFactory.getLogger(SensorResource.class);
 
-    @SuppressWarnings("rawtypes")
     @Override
     public List<SensorSummary> list(final String application, final String entityToken) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+                    Entitlements.getEntitlementContext().user(), entity);
+        }
 
-        return Lists.newArrayList(transform(filter(entity.getEntityType().getSensors(), AttributeSensor.class),
-                new Function<AttributeSensor, SensorSummary>() {
-                    @Override
-                    public SensorSummary apply(AttributeSensor sensor) {
-                        return SensorTransformer.sensorSummary(entity, sensor);
-                    }
-                }));
+        List<SensorSummary> result = Lists.newArrayList();
+        
+        for (AttributeSensor<?> sensor : filter(entity.getEntityType().getSensors(), AttributeSensor.class)) {
+            // Exclude config that user is not allowed to see
+            if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_SENSOR, new EntityAndItem<String>(entity, sensor.getName()))) {
+                log.trace("User {} not authorized to see sensor {} of entity {}; excluding from AttributeSensor list results", 
+                        new Object[] {Entitlements.getEntitlementContext().user(), sensor.getName(), entity});
+                continue;
+            }
+            result.add(SensorTransformer.sensorSummary(entity, sensor));
+        }
+        
+        return result;
     }
 
     @Override
     public Map<String, Object> batchSensorRead(final String application, final String entityToken, final Boolean raw) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+                    Entitlements.getEntitlementContext().user(), entity);
+        }
+
         Map<String, Object> sensorMap = Maps.newHashMap();
         @SuppressWarnings("rawtypes")
         Iterable<AttributeSensor> sensors = filter(entity.getEntityType().getSensors(), AttributeSensor.class);
 
         for (AttributeSensor<?> sensor : sensors) {
+            // Exclude sensors that user is not allowed to see
+            if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_SENSOR, new EntityAndItem<String>(entity, sensor.getName()))) {
+                log.trace("User {} not authorized to see sensor {} of entity {}; excluding from current-state results", 
+                        new Object[] {Entitlements.getEntitlementContext().user(), sensor.getName(), entity});
+                continue;
+            }
+
             Object value = entity.getAttribute(findSensor(entity, sensor.getName()));
             sensorMap.put(sensor.getName(), 
                 resolving(value).preferJson(true).asJerseyOutermostReturnValue(false).raw(raw).context(entity).timeout(Duration.ZERO).renderAs(sensor).resolve());
@@ -82,6 +102,16 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
     protected Object get(boolean preferJson, String application, String entityToken, String sensorName, Boolean raw) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
         AttributeSensor<?> sensor = findSensor(entity, sensorName);
+        
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s'",
+                    Entitlements.getEntitlementContext().user(), entity);
+        }
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_SENSOR, new EntityAndItem<String>(entity, sensor.getName()))) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to see entity '%s' sensor '%s'",
+                    Entitlements.getEntitlementContext().user(), entity, sensor.getName());
+        }
+        
         Object value = entity.getAttribute(sensor);
         return resolving(value).preferJson(preferJson).asJerseyOutermostReturnValue(true).raw(raw).context(entity).timeout(ValueResolver.PRETTY_QUICK_WAIT).renderAs(sensor).resolve();
     }
@@ -140,6 +170,11 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
     @Override
     public void delete(String application, String entityToken, String sensorName) {
         final Entity entity = brooklyn().getEntity(application, entityToken);
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+                Entitlements.getEntitlementContext().user(), entity);
+        }
+        
         AttributeSensor<?> sensor = findSensor(entity, sensorName);
         if (log.isDebugEnabled())
             log.debug("REST user "+Entitlements.getEntitlementContext()+" deleting sensor "+sensorName);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java
new file mode 100644
index 0000000..c851b48
--- /dev/null
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AbstractRestApiEntitlementsTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.brooklyn.rest.entitlement;
+
+import static org.apache.brooklyn.util.http.HttpTool.httpClientBuilder;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.net.URI;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.internal.BrooklynProperties;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
+import org.apache.brooklyn.core.mgmt.entitlement.PerUserEntitlementManager;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.rest.BrooklynRestApiLauncher;
+import org.apache.brooklyn.rest.BrooklynRestApiLauncherTestFixture;
+import org.apache.brooklyn.util.http.HttpAsserts;
+import org.apache.brooklyn.util.http.HttpTool;
+import org.apache.brooklyn.util.http.HttpToolResponse;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.HttpClient;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+/**
+ * Sets up the REST api with some standard users, ready for testing entitlements.
+ */
+public abstract class AbstractRestApiEntitlementsTest extends BrooklynRestApiLauncherTestFixture {
+
+    protected ManagementContext mgmt;
+    protected TestApplication app;
+    protected TestEntity entity;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
+        props.put(Entitlements.GLOBAL_ENTITLEMENT_MANAGER.getName(), PerUserEntitlementManager.class.getName());
+        props.put(PerUserEntitlementManager.PER_USER_ENTITLEMENTS_CONFIG_PREFIX+".myRoot", "root");
+        props.put(PerUserEntitlementManager.PER_USER_ENTITLEMENTS_CONFIG_PREFIX+".myReadonly", "readonly");
+        props.put(PerUserEntitlementManager.PER_USER_ENTITLEMENTS_CONFIG_PREFIX+".myMinimal", "minimal");
+        props.put(PerUserEntitlementManager.PER_USER_ENTITLEMENTS_CONFIG_PREFIX+".myCustom", StaticDelegatingEntitlementManager.class.getName());
+        
+        mgmt = LocalManagementContextForTests.builder(true).useProperties(props).build();
+        app = mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class)
+                .child(EntitySpec.create(TestEntity.class))
+                        .configure(TestEntity.CONF_NAME, "myname"));
+        entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+        
+        useServerForTest(BrooklynRestApiLauncher.launcher()
+                .managementContext(mgmt)
+                .forceUseOfDefaultCatalogWithJavaClassPath(true)
+                .securityProvider(AuthenticateAnyoneSecurityProvider.class)
+                .start());
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (mgmt != null) Entities.destroyAll(mgmt);
+    }
+    
+    protected HttpClient newClient(String user) throws Exception {
+        return httpClientBuilder()
+                .uri(getBaseUri())
+                .credentials(new UsernamePasswordCredentials(user, "ignoredPassword"))
+                .build();
+    }
+
+    protected String httpGet(String user, String path) throws Exception {
+        HttpToolResponse response = HttpTool.httpGet(newClient(user), URI.create(getBaseUri()).resolve(path), ImmutableMap.<String, String>of());
+        assertTrue(HttpAsserts.isHealthyStatusCode(response.getResponseCode()), "code="+response.getResponseCode()+"; reason="+response.getReasonPhrase());
+        return response.getContentAsString();
+    }
+    
+    protected String assertPermitted(String user, String path) throws Exception {
+        return httpGet(user, path);
+    }
+
+    protected void assertForbidden(String user, String path) throws Exception {
+        HttpToolResponse response = HttpTool.httpGet(newClient(user), URI.create(getBaseUri()).resolve(path), ImmutableMap.<String, String>of());
+        assertEquals(response.getResponseCode(), 401, "code="+response.getResponseCode()+"; reason="+response.getReasonPhrase()+"; content="+response.getContentAsString());
+    }
+
+    protected void assert404(String user, String path) throws Exception {
+        HttpToolResponse response = HttpTool.httpGet(newClient(user), URI.create(getBaseUri()).resolve(path), ImmutableMap.<String, String>of());
+        assertEquals(response.getResponseCode(), 404, "code="+response.getResponseCode()+"; reason="+response.getReasonPhrase()+"; content="+response.getContentAsString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AuthenticateAnyoneSecurityProvider.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AuthenticateAnyoneSecurityProvider.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AuthenticateAnyoneSecurityProvider.java
new file mode 100644
index 0000000..b7264b2
--- /dev/null
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/AuthenticateAnyoneSecurityProvider.java
@@ -0,0 +1,41 @@
+/*
+ * 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.brooklyn.rest.entitlement;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.brooklyn.rest.security.provider.SecurityProvider;
+
+public class AuthenticateAnyoneSecurityProvider implements SecurityProvider {
+
+    @Override
+    public boolean isAuthenticated(HttpSession session) {
+        return false;
+    }
+
+    @Override
+    public boolean authenticate(HttpSession session, String user, String password) {
+        return user != null;
+    }
+
+    @Override
+    public boolean logout(HttpSession session) {
+        return false;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/EntityConfigApiEntitlementsTest.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/EntityConfigApiEntitlementsTest.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/EntityConfigApiEntitlementsTest.java
new file mode 100644
index 0000000..cbda515
--- /dev/null
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/EntityConfigApiEntitlementsTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.brooklyn.rest.entitlement;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementContext;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.config.render.RendererHints;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.rest.api.SensorApi;
+import org.apache.brooklyn.rest.resources.SensorResource;
+import org.apache.brooklyn.test.Asserts;
+import org.testng.annotations.Test;
+
+/**
+ * Test the {@link SensorApi} implementation.
+ * <p>
+ * Check that {@link SensorResource} correctly renders {@link AttributeSensor}
+ * values, including {@link RendererHints.DisplayValue} hints.
+ */
+@Test(singleThreaded = true)
+public class EntityConfigApiEntitlementsTest extends AbstractRestApiEntitlementsTest {
+
+    @Test(groups = "Integration")
+    public void testGet() throws Exception {
+        String path = "/v1/applications/"+app.getId()+"/entities/"+entity.getId()+"/config/"+TestEntity.CONF_NAME.getName();
+        String val = "\"myname\"";
+        
+        assertEquals(httpGet("myRoot", path), val);
+        assertEquals(httpGet("myReadonly", path), val);
+        assert404("myMinimal", path); // can't see app, to retrieve entity
+        assert404("unrecognisedUser", path);
+
+        StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveConfig(entity, TestEntity.CONF_NAME.getName()));
+        assertEquals(httpGet("myCustom", path), val);
+        
+        StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveConfig(entity, "differentConfName"));
+        assertForbidden("myCustom", path);
+    }
+    
+    @Test(groups = "Integration")
+    public void testCurrentState() throws Exception {
+        String path = "/v1/applications/"+app.getId()+"/entities/"+entity.getId()+"/config/current-state";
+        String confName = TestEntity.CONF_NAME.getName();
+        String regex = ".*"+confName+".*myname.*";
+        
+        Asserts.assertStringMatchesRegex(httpGet("myRoot", path), regex);
+        Asserts.assertStringMatchesRegex(httpGet("myReadonly", path), regex);
+        assert404("myMinimal", path); // can't see app, to retrieve entity
+        assert404("unrecognisedUser", path);
+
+        StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveConfig(entity, confName));
+        Asserts.assertStringMatchesRegex(httpGet("myCustom", path), regex);
+        
+        StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveConfig(entity, "differentConfName"));
+        String resp = httpGet("myCustom", path);
+        assertFalse(resp.matches(regex), "resp="+resp);
+    }
+    
+    public static class SeeSelectiveConfig implements EntitlementManager {
+        private final Entity entity;
+        private final String regex;
+        
+        public SeeSelectiveConfig(Entity entity, String regex) {
+            this.entity = entity;
+            this.regex = regex;
+        }
+        @Override 
+        @SuppressWarnings("unchecked")
+        public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
+            String type = entitlementClass.entitlementClassIdentifier();
+            if (Entitlements.SEE_CONFIG.entitlementClassIdentifier().equals(type)) {
+                EntityAndItem<String> entityAndItem = (EntityAndItem<String>) entitlementClassArgument;
+                return entity.equals(entityAndItem.getEntity()) && entityAndItem.getItem().matches(regex);
+            } else {
+                return true;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/SensorApiEntitlementsTest.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/SensorApiEntitlementsTest.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/SensorApiEntitlementsTest.java
new file mode 100644
index 0000000..dab72ec
--- /dev/null
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/SensorApiEntitlementsTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.brooklyn.rest.entitlement;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementContext;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.config.render.RendererHints;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
+import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.rest.api.SensorApi;
+import org.apache.brooklyn.rest.resources.SensorResource;
+import org.apache.brooklyn.test.Asserts;
+import org.testng.annotations.Test;
+
+/**
+ * Test the {@link SensorApi} implementation.
+ * <p>
+ * Check that {@link SensorResource} correctly renders {@link AttributeSensor}
+ * values, including {@link RendererHints.DisplayValue} hints.
+ */
+@Test(singleThreaded = true)
+public class SensorApiEntitlementsTest extends AbstractRestApiEntitlementsTest {
+
+    @Test(groups = "Integration")
+    public void testGet() throws Exception {
+        entity.sensors().set(TestEntity.NAME, "myval");
+        
+        String sensorName = TestEntity.NAME.getName();
+        String path = "/v1/applications/"+app.getId()+"/entities/"+entity.getId()+"/sensors/"+sensorName;
+        String val = "\"myval\"";
+        
+        assertEquals(httpGet("myRoot", path), val);
+        assertEquals(httpGet("myReadonly", path), val);
+        assert404("myMinimal", path); // can't see app, to retrieve entity
+        assert404("unrecognisedUser", path);
+
+        StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveSensor(entity, sensorName));
+        assertEquals(httpGet("myCustom", path), val);
+        
+        StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveSensor(entity, "differentConfName"));
+        assertForbidden("myCustom", path);
+    }
+    
+    @Test(groups = "Integration")
+    public void testCurrentState() throws Exception {
+        entity.sensors().set(TestEntity.NAME, "myval");
+        
+        String path = "/v1/applications/"+app.getId()+"/entities/"+entity.getId()+"/sensors/current-state";
+        String sensorName = TestEntity.NAME.getName();
+        String regex = ".*"+sensorName+".*myval.*";
+        
+        Asserts.assertStringMatchesRegex(httpGet("myRoot", path), regex);
+        Asserts.assertStringMatchesRegex(httpGet("myReadonly", path), regex);
+        assert404("myMinimal", path); // can't see app, to retrieve entity
+        assert404("unrecognisedUser", path);
+
+        StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveSensor(entity, sensorName));
+        Asserts.assertStringMatchesRegex(httpGet("myCustom", path), regex);
+        
+        StaticDelegatingEntitlementManager.setDelegate(new SeeSelectiveSensor(entity, "differentSensorName"));
+        String resp = httpGet("myCustom", path);
+        assertFalse(resp.matches(regex), "resp="+resp);
+    }
+    
+    public static class SeeSelectiveSensor implements EntitlementManager {
+        private final Entity entity;
+        private final String regex;
+        
+        public SeeSelectiveSensor(Entity entity, String regex) {
+            this.entity = entity;
+            this.regex = regex;
+        }
+        @Override 
+        @SuppressWarnings("unchecked")
+        public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
+            String type = entitlementClass.entitlementClassIdentifier();
+            if (Entitlements.SEE_SENSOR.entitlementClassIdentifier().equals(type)) {
+                EntityAndItem<String> entityAndItem = (EntityAndItem<String>) entitlementClassArgument;
+                return entity.equals(entityAndItem.getEntity()) && entityAndItem.getItem().matches(regex);
+            } else {
+                return true;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/ServerApiEntitlementsTest.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/ServerApiEntitlementsTest.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/ServerApiEntitlementsTest.java
new file mode 100644
index 0000000..afa42cb
--- /dev/null
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/ServerApiEntitlementsTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.brooklyn.rest.entitlement;
+
+import org.testng.annotations.Test;
+
+@Test(singleThreaded = true)
+public class ServerApiEntitlementsTest extends AbstractRestApiEntitlementsTest {
+
+    @Test(groups = "Integration")
+    public void testGetHealthy() throws Exception {
+        String path = "/v1/server/up";
+        assertPermitted("myRoot", path);
+        assertForbidden("myReadonly", path);
+        assertForbidden("myMinimal", path);
+        assertForbidden("unrecognisedUser", path);
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a0557178/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/StaticDelegatingEntitlementManager.java
----------------------------------------------------------------------
diff --git a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/StaticDelegatingEntitlementManager.java b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/StaticDelegatingEntitlementManager.java
new file mode 100644
index 0000000..4370ad6
--- /dev/null
+++ b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/entitlement/StaticDelegatingEntitlementManager.java
@@ -0,0 +1,37 @@
+/*
+ * 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.brooklyn.rest.entitlement;
+
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementContext;
+import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
+
+public class StaticDelegatingEntitlementManager implements EntitlementManager {
+
+    private static volatile EntitlementManager delegate;
+    
+    public static void setDelegate(EntitlementManager val) {
+        delegate = val;
+    }
+    
+    @Override
+    public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
+        return (delegate != null) ? delegate.isEntitled(context, entitlementClass, entitlementClassArgument) : false;
+    }
+}