You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2012/12/14 12:43:51 UTC
svn commit: r1421804 - in
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak:
security/authorization/ security/authorization/restriction/
spi/security/authorization/
Author: angela
Date: Fri Dec 14 11:43:50 2012
New Revision: 1421804
URL: http://svn.apache.org/viewvc?rev=1421804&view=rev
Log:
OAK-51 : Access Control Management (WIP)
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ImmutableACL.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java?rev=1421804&r1=1421803&r2=1421804&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImpl.java Fri Dec 14 11:43:50 2012
@@ -60,6 +60,7 @@ import org.apache.jackrabbit.oak.securit
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.ACE;
import org.apache.jackrabbit.oak.spi.security.authorization.ACL;
+import org.apache.jackrabbit.oak.spi.security.authorization.ImmutableACL;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
@@ -135,7 +136,7 @@ public class AccessControlManagerImpl im
checkPermission(tree);
checkIsAccessControlContent(tree);
- AccessControlPolicy policy = readAccessControlPolicy(absPath, tree);
+ AccessControlPolicy policy = readACL(absPath, tree, false);
if (policy != null) {
return new AccessControlPolicy[] {policy};
} else {
@@ -150,7 +151,7 @@ public class AccessControlManagerImpl im
checkIsAccessControlContent(tree);
List<AccessControlPolicy> effective = new ArrayList<AccessControlPolicy>();
- AccessControlPolicy policy = readAccessControlPolicy(absPath, tree);
+ AccessControlPolicy policy = readACL(absPath, tree, true);
if (policy != null) {
effective.add(policy);
}
@@ -158,7 +159,7 @@ public class AccessControlManagerImpl im
String parentPath = Text.getRelativeParent(tree.getPath(), 1);
while (!parentPath.isEmpty()) {
Tree t = root.getTree(parentPath);
- AccessControlPolicy plc = readAccessControlPolicy(parentPath, t);
+ AccessControlPolicy plc = readACL(parentPath, t, true);
if (plc != null) {
effective.add(plc);
}
@@ -187,7 +188,7 @@ public class AccessControlManagerImpl im
} else {
String mixinName = getMixinName(absPath);
if (ntMgr.isNodeType(tree, mixinName) || ntMgr.getEffectiveNodeType(tree).supportsMixin(mixinName)) {
- policy = new ACL(absPath, restrictionProvider, namePathMapper);
+ policy = new NodeACL(absPath);
} else {
log.warn("Node {} cannot be made access controllable.", absPath);
}
@@ -203,45 +204,57 @@ public class AccessControlManagerImpl im
@Override
public void setPolicy(String absPath, AccessControlPolicy policy) throws RepositoryException {
- Tree tree = getTree(absPath);
- checkPermission(tree);
- checkIsAccessControlContent(tree);
checkValidPolicy(absPath, policy);
- NodeUtil aclNode = getAclNode(absPath, tree);
- if (aclNode != null) {
- // remove all existing aces
- for (Tree aceTree : aclNode.getTree().getChildren()) {
- aceTree.remove();
- }
+ if (policy instanceof PrincipalACL) {
+ // TODO
+ throw new RepositoryException("not yet implemented");
} else {
- aclNode = createAclTree(absPath, tree);
- }
+ Tree tree = getTree(absPath);
+ checkPermission(tree);
+ checkIsAccessControlContent(tree);
+
+ NodeUtil aclNode = getAclNode(absPath, tree);
+ if (aclNode != null) {
+ // remove all existing aces
+ for (Tree aceTree : aclNode.getTree().getChildren()) {
+ aceTree.remove();
+ }
+ } else {
+ aclNode = createAclTree(absPath, tree);
+ }
- ACL acl = (ACL) policy;
- for (ACE ace : acl.getACEs()) {
- String nodeName = generateAceName(aclNode, ace.isAllow());
- String ntName = (ace.isAllow()) ? NT_REP_GRANT_ACE : NT_REP_DENY_ACE;
-
- NodeUtil aceNode = aclNode.addChild(nodeName, ntName);
- aceNode.setString(REP_PRINCIPAL_NAME, ace.getPrincipal().getName());
- aceNode.setNames(REP_PRIVILEGES, ace.getPrivilegeNames());
- restrictionProvider.writeRestrictions(absPath, aceNode.getTree(), ace.getRestrictionSet());
+ ACL acl = (ACL) policy;
+ for (ACE ace : acl.getACEs()) {
+ String nodeName = generateAceName(aclNode, ace.isAllow());
+ String ntName = (ace.isAllow()) ? NT_REP_GRANT_ACE : NT_REP_DENY_ACE;
+
+ NodeUtil aceNode = aclNode.addChild(nodeName, ntName);
+ aceNode.setString(REP_PRINCIPAL_NAME, ace.getPrincipal().getName());
+ aceNode.setNames(REP_PRIVILEGES, ace.getPrivilegeNames());
+ restrictionProvider.writeRestrictions(absPath, aceNode.getTree(), ace.getRestrictionSet());
+ }
}
}
@Override
public void removePolicy(String absPath, AccessControlPolicy policy) throws RepositoryException {
- Tree tree = getTree(absPath);
- checkPermission(tree);
- checkIsAccessControlContent(tree);
checkValidPolicy(absPath, policy);
- NodeUtil aclNode = getAclNode(absPath, tree);
- if (aclNode != null) {
- aclNode.getTree().remove();
+ if (policy instanceof PrincipalACL) {
+ // TODO
+ throw new RepositoryException("not yet implemented");
} else {
- throw new AccessControlException("No policy to remove at " + absPath);
+ Tree tree = getTree(absPath);
+ checkPermission(tree);
+ checkIsAccessControlContent(tree);
+
+ NodeUtil aclNode = getAclNode(absPath, tree);
+ if (aclNode != null) {
+ aclNode.getTree().remove();
+ } else {
+ throw new AccessControlException("No policy to remove at " + absPath);
+ }
}
}
@@ -252,7 +265,7 @@ public class AccessControlManagerImpl im
if (aceResult.getSize() > 0) {
return new JackrabbitAccessControlPolicy[0];
} else {
- return new JackrabbitAccessControlPolicy[] {getPrincipalACL(principal, null)};
+ return new JackrabbitAccessControlPolicy[] {createPrincipalACL(principal, null)};
}
}
@@ -260,7 +273,7 @@ public class AccessControlManagerImpl im
public JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws RepositoryException {
Result aceResult = searchAces(Collections.<Principal>singleton(principal));
if (aceResult.getSize() > 0) {
- return new JackrabbitAccessControlPolicy[] {getPrincipalACL(principal, aceResult)};
+ return new JackrabbitAccessControlPolicy[] {createPrincipalACL(principal, aceResult)};
} else {
return new JackrabbitAccessControlPolicy[0];
}
@@ -275,7 +288,7 @@ public class AccessControlManagerImpl im
Tree accessControlledTree = aclTree.getParent();
String path = (REP_REPO_POLICY.equals(aclTree.getName())) ? null : accessControlledTree.getPath();
- AccessControlPolicy policy = readAccessControlPolicy(path, accessControlledTree);
+ AccessControlPolicy policy = readACL(path, accessControlledTree, true);
if (policy != null) {
effective.add(policy);
}
@@ -346,9 +359,16 @@ public class AccessControlManagerImpl im
}
private void checkValidPolicy(String jcrPath, AccessControlPolicy policy) throws AccessControlException {
- // TODO
- // TODO: make sure policy is jackrabbit acl
- // TODO: make sure path matches path of policy
+ if (policy instanceof NodeACL) {
+ String path = ((NodeACL) policy).getPath();
+ if ((path == null && jcrPath != null) || (path != null && !path.equals(jcrPath))) {
+ throw new AccessControlException("Invalid access control policy " + policy + ": path mismatch " + jcrPath);
+ }
+ } if (policy instanceof PrincipalACL) {
+ // TODO: validate
+ } else {
+ throw new AccessControlException("Invalid access control policy " + policy);
+ }
}
private boolean isAccessControlled(Tree tree, String nodeTypeName) throws RepositoryException {
@@ -360,8 +380,9 @@ public class AccessControlManagerImpl im
}
@CheckForNull
- private AccessControlPolicy readAccessControlPolicy(String jcrPath, Tree accessControlledTree) throws RepositoryException {
- AccessControlPolicy acl = null;
+ private ACL readACL(String jcrPath, Tree accessControlledTree,
+ boolean isReadOnly) throws RepositoryException {
+ ACL acl = null;
String aclName = getAclName(jcrPath);
String mixinName = getMixinName(jcrPath);
if (isAccessControlled(accessControlledTree, mixinName) && accessControlledTree.hasChild(aclName)) {
@@ -369,17 +390,21 @@ public class AccessControlManagerImpl im
List<ACE> entries = new ArrayList<ACE>();
for (Tree child : aclTree.getChildren()) {
if (isACE(child)) {
- entries.add(readAccessControlEntry(jcrPath, child, restrictionProvider));
+ entries.add(readACE(jcrPath, child, restrictionProvider));
}
}
- acl = new ACL(jcrPath, entries, restrictionProvider, namePathMapper);
+ if (isReadOnly) {
+ acl = new ImmutableACL(jcrPath, entries, restrictionProvider, namePathMapper);
+ } else {
+ acl = new NodeACL(jcrPath, entries);
+ }
}
return acl;
}
@Nonnull
- private ACE readAccessControlEntry(String jcrPath, Tree aceTree,
- RestrictionProvider restrictionProvider) throws RepositoryException {
+ private ACE readACE(String jcrPath, Tree aceTree, RestrictionProvider restrictionProvider)
+ throws RepositoryException {
NodeUtil aceNode = new NodeUtil(aceTree);
Principal principal = principalProvider.getPrincipal(aceNode.getString(REP_PRINCIPAL_NAME, null));
boolean isAllow = aceNode.hasPrimaryNodeTypeName(NT_REP_GRANT_ACE);
@@ -387,8 +412,7 @@ public class AccessControlManagerImpl im
return new ACE(principal, getPrivileges(aceNode), isAllow, restrictions, namePathMapper);
}
- @Nonnull
- private ACL getPrincipalACL(Principal principal, Result aceResult) throws RepositoryException {
+ private ACL createPrincipalACL(Principal principal, Result aceResult) throws RepositoryException {
// TODO: specific path indicating the principal-based nature of the
// TODO: ACL... this could also be the path of the compiled permissions
// TODO: for this principal.
@@ -411,11 +435,11 @@ public class AccessControlManagerImpl im
} else {
jcrPath = Text.getRelativeParent(aclPath, 1);
}
- entries.add(readAccessControlEntry(jcrPath, aceTree, pbRestrictions));
+ entries.add(readACE(jcrPath, aceTree, pbRestrictions));
}
}
}
- return new ACL(principalBasedPath, entries, pbRestrictions, namePathMapper);
+ return new PrincipalACL(principalBasedPath, entries, pbRestrictions, namePathMapper);
}
/**
@@ -520,7 +544,28 @@ public class AccessControlManagerImpl im
return aceName;
}
- // TODO review again.
+ //--------------------------------------------------------------------------
+ private class NodeACL extends ACL {
+
+ private NodeACL(String jcrPath) {
+ this(jcrPath, null);
+ }
+
+ private NodeACL(String jcrPath, List<ACE> entries) {
+ super(jcrPath, entries, restrictionProvider, namePathMapper);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ // TODO review again
+
+ private class PrincipalACL extends ACL {
+
+ private PrincipalACL(String jcrPath, List<ACE> entries, RestrictionProvider restrictionProvider, NamePathMapper namePathMapper) {
+ super(jcrPath, entries, restrictionProvider, namePathMapper);
+ }
+ }
+
private static class PrincipalRestrictionProvider extends RestrictionProviderImpl {
private PrincipalRestrictionProvider(NamePathMapper namePathMapper) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java?rev=1421804&r1=1421803&r2=1421804&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/restriction/RestrictionProviderImpl.java Fri Dec 14 11:43:50 2012
@@ -16,7 +16,6 @@
*/
package org.apache.jackrabbit.oak.security.authorization.restriction;
-import java.security.AccessControlException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -26,6 +25,7 @@ import javax.jcr.NamespaceRegistry;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
+import javax.jcr.security.AccessControlException;
import com.google.common.collect.ImmutableSet;
import org.apache.jackrabbit.oak.api.PropertyState;
@@ -78,15 +78,15 @@ public class RestrictionProviderImpl imp
}
@Override
- public Set<Restriction> readRestrictions(String jcrPath, Tree aceTree) throws javax.jcr.security.AccessControlException {
+ public Set<Restriction> readRestrictions(String jcrPath, Tree aceTree) throws AccessControlException {
// TODO
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("not yet implemented");
}
@Override
- public void writeRestrictions(String jcrPath, Tree aceTree, Set<Restriction> restrictions) throws javax.jcr.security.AccessControlException {
+ public void writeRestrictions(String jcrPath, Tree aceTree, Set<Restriction> restrictions) throws AccessControlException {
// TODO
-
+ throw new UnsupportedOperationException("not yet implemented");
}
@Override
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ImmutableACL.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ImmutableACL.java?rev=1421804&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ImmutableACL.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/ImmutableACL.java Fri Dec 14 11:43:50 2012
@@ -0,0 +1,130 @@
+/*
+ * 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.jackrabbit.oak.spi.security.authorization;
+
+import java.security.Principal;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlException;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.Privilege;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
+
+/**
+ * An implementation of the {@code JackrabbitAccessControlList} interface that only
+ * allows for reading. The write methods throw an {@code AccessControlException}.
+ */
+public class ImmutableACL extends ACL {
+
+ private int hashCode;
+
+ /**
+ * Construct a new {@code UnmodifiableAccessControlList}
+ *
+ * @param jcrPath
+ * @param entries
+ * @param restrictionProvider
+ * @param namePathMapper
+ */
+ public ImmutableACL(String jcrPath, List<ACE> entries,
+ RestrictionProvider restrictionProvider,
+ NamePathMapper namePathMapper) {
+ super(jcrPath, getImmutableEntries(entries), restrictionProvider, namePathMapper);
+ }
+
+ private static List<ACE> getImmutableEntries(List<ACE> entries) {
+ return (entries == null) ? Collections.<ACE>emptyList() : ImmutableList.copyOf(entries);
+ }
+
+ //--------------------------------------------------< AccessControlList >---
+ /**
+ * @see AccessControlList#addAccessControlEntry(java.security.Principal, javax.jcr.security.Privilege[])
+ */
+ public boolean addAccessControlEntry(Principal principal,
+ Privilege[] privileges)
+ throws AccessControlException, RepositoryException {
+ throw new AccessControlException("Immutable ACL. Use AccessControlManager#getApplicablePolicies in order to obtain an modifiable ACL.");
+ }
+
+ /**
+ * @see AccessControlList#removeAccessControlEntry(AccessControlEntry)
+ */
+ public void removeAccessControlEntry(AccessControlEntry ace)
+ throws AccessControlException, RepositoryException {
+ throw new AccessControlException("Immutable ACL. Use AccessControlManager#getApplicablePolicies in order to obtain an modifiable ACL.");
+ }
+
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean)
+ */
+ public boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow) throws AccessControlException {
+ throw new AccessControlException("Immutable ACL. Use AccessControlManager#getPolicy or #getApplicablePolicies in order to obtain an modifiable ACL.");
+ }
+
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean, Map)
+ */
+ public boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow, Map<String, Value> restrictions) throws AccessControlException {
+ throw new AccessControlException("Immutable ACL. Use AccessControlManager#getPolicy or #getApplicablePolicies in order to obtain an modifiable ACL.");
+ }
+
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#orderBefore(AccessControlEntry, AccessControlEntry)
+ */
+ public void orderBefore(AccessControlEntry srcEntry, AccessControlEntry destEntry) throws AccessControlException {
+ throw new AccessControlException("Immutable ACL. Use AccessControlManager#getPolicy or #getApplicablePolicy in order to obtain a modifiable ACL.");
+ }
+
+ //-------------------------------------------------------------< Object >---
+ /**
+ * @see Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ if (hashCode == 0) {
+ int result = 17;
+ result = 37 * result + (getPath() != null ? getPath().hashCode() : 0);
+ for (ACE entry : getACEs()) {
+ result = 37 * result + entry.hashCode();
+ }
+ hashCode = result;
+ }
+ return hashCode;
+ }
+
+ /**
+ * @see Object#equals(Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof ImmutableACL) {
+ return super.equals(obj);
+ }
+ return false;
+ }
+}
\ No newline at end of file