Skip to content

Instantly share code, notes, and snippets.

@gschueler
Created November 16, 2010 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gschueler/702744 to your computer and use it in GitHub Desktop.
Save gschueler/702744 to your computer and use it in GitHub Desktop.
diff --git a/core/src/java/com/dtolabs/rundeck/core/authorization/providers/Policies.java b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/Policies.java
index bbe8b2b..7979ab0 100644
--- a/core/src/java/com/dtolabs/rundeck/core/authorization/providers/Policies.java
+++ b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/Policies.java
@@ -16,50 +16,22 @@
package com.dtolabs.rundeck.core.authorization.providers;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-import javax.security.auth.Subject;
-import javax.xml.namespace.NamespaceContext;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Document;
+import com.dtolabs.rundeck.core.authorization.Attribute;
+import com.dtolabs.rundeck.core.authorization.Explanation;
+import com.dtolabs.rundeck.core.authorization.Explanation.Code;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import com.dtolabs.rundeck.core.authentication.Group;
-import com.dtolabs.rundeck.core.authentication.LdapGroup;
-import com.dtolabs.rundeck.core.authentication.Username;
-import com.dtolabs.rundeck.core.authorization.Attribute;
-import com.dtolabs.rundeck.core.authorization.Explanation;
-import com.dtolabs.rundeck.core.authorization.Explanation.Code;
+import javax.security.auth.Subject;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.*;
+import java.util.regex.Pattern;
/**
* Policies represent the policies as described in the policies file(s).
@@ -68,25 +40,27 @@ import com.dtolabs.rundeck.core.authorization.Explanation.Code;
*/
public class Policies {
- private static final String NS_AD = "http://dtolabs.com/rundeck/activedirectory";
- private static final String NS_LDAP = "http://dtolabs.com/rundeck/ldap";
- private final XPath xpath = XPathFactory.newInstance().newXPath();
+ static final String NS_AD = "http://dtolabs.com/rundeck/activedirectory";
+ static final String NS_LDAP = "http://dtolabs.com/rundeck/ldap";
+ private static final XPath xpath = XPathFactory.newInstance().newXPath();
private final List<File> policyFiles = new ArrayList<File>();
- private final List<Document> aclpolicies = new ArrayList<Document>();
-
+
private final XPathExpression count;
private final XPathExpression allPolicies;
private final XPathExpression byUserName;
private final XPathExpression byGroup;
+ private PoliciesCache cache;
+
- public Policies() {
+ public Policies(final PoliciesCache cache) {
+ this.cache = cache;
xpath.setNamespaceContext(new NamespaceContext() {
-
+
@SuppressWarnings("rawtypes")
public Iterator getPrefixes(String namespaceURI) { return null; }
public String getPrefix(String namespaceURI) { return null; }
-
+
public String getNamespaceURI(String prefix) {
if(prefix.equals("ldap")) {
return NS_LDAP;
@@ -97,7 +71,7 @@ public class Policies {
}
}
});
-
+
try {
this.count = xpath.compile("count(//policy)");
this.allPolicies = xpath.compile("//policy");
@@ -106,34 +80,18 @@ public class Policies {
} catch (XPathExpressionException e) {
throw new IllegalArgumentException(e);
}
-
-
- }
-
- public void add(File file) throws SAXException, IOException, ParserConfigurationException {
-
- /* Just checking to make sure it's a well formed document. */
- DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
- domFactory.setNamespaceAware(true);
- DocumentBuilder builder = domFactory.newDocumentBuilder();
- aclpolicies.add(builder.parse(file));
-
- this.policyFiles.add(file);
- }
-
- public void remove(File file) {
- this.policyFiles.remove(file);
}
public int count() {
int count = 0;
- for(Document f : aclpolicies) {
+ for(PoliciesDocument f : cache) {
+
try {
- Double n = (Double)this.count.evaluate(f, XPathConstants.NUMBER);
+ Double n = f.countPolicies();
count += n;
} catch (XPathExpressionException e) {
// TODO squash
- }
+ }
}
return count;
}
@@ -145,21 +103,13 @@ public class Policies {
* @throws PoliciesParseException Thrown when there is a problem parsing a file.
*/
public static Policies load(File rootPath) throws IOException, PoliciesParseException {
-
- Policies p = new Policies();
-
- for(File f : rootPath.listFiles(new FilenameFilter(){
- public boolean accept(File dir, String name) {
- return name.endsWith(".aclpolicy");
- }})) {
- try {
- p.add(f);
- } catch (SAXException e) {
- throw new PoliciesParseException(e);
- } catch (ParserConfigurationException e) {
- throw new PoliciesParseException(e);
- }
- }
+
+ Policies p = null;
+ try {
+ p = new Policies(new PoliciesCache(rootPath));
+ } catch (ParserConfigurationException e) {
+ throw new PoliciesParseException(e);
+ }
return p;
}
@@ -167,95 +117,9 @@ public class Policies {
public List<Context> narrowContext(Subject subject, Set<Attribute> environment) {
List<Context> matchedContexts = new ArrayList<Context>();
- for(Document f : aclpolicies) {
+ for(final PoliciesDocument f : cache) {
try {
- NodeList policiesToEvaluate = (NodeList)this.allPolicies.evaluate(f, XPathConstants.NODESET);
- for(int i = 0; i < policiesToEvaluate.getLength(); i++) {
-
- Node policy = policiesToEvaluate.item(i);
-
- // What constitutes a match?
- // * The username matches exactly 1 in the context.
- // * 1 subject group matches 1 group. non disjoint sets.
- //
- // First match stops the search.
-
- // TODO: time of day check.
-
- long userMatchStart = System.currentTimeMillis();
- NodeList usernames = (NodeList) this.byUserName.evaluate(policy, XPathConstants.NODESET);
-
- Set<String> policyUsers = new HashSet<String>(usernames.getLength());
- for(int u = 0; u < usernames.getLength(); u++) {
- Node username = usernames.item(u);
- policyUsers.add(username.getNodeValue());
- }
-
- Set<Username> userPrincipals = subject.getPrincipals(Username.class);
- if(userPrincipals.size() > 0) {
- Set<String> usernamePrincipals = new HashSet<String>();
- for(Username username: userPrincipals) {
- usernamePrincipals.add(username.getName());
- }
-
- if(!Collections.disjoint(policyUsers, usernamePrincipals)) {
- matchedContexts.add(new Context(policy));
- System.err.println("Policy: " + i + " Matched on User: " + (System.currentTimeMillis() - userMatchStart) + "ms");
- break;
- }
- }
- System.err.println("Policy: " + i + " No match on User: " + (System.currentTimeMillis() - userMatchStart) + "ms");
-
-
- Set<Group> groupPrincipals = subject.getPrincipals(Group.class);
- if(groupPrincipals.size() > 0) {
- // no username matched, check groups.
- long groupCollectStart = System.currentTimeMillis();
- NodeList groups = (NodeList) this.byGroup.evaluate(policy, XPathConstants.NODESET);
- Set<Object> policyGroups = new HashSet<Object>(groups.getLength());
- for(int g = 0; g < groups.getLength(); g++) {
- Node group = groups.item(g);
- String ns = group.getNamespaceURI();
- if(ns == null) {
- policyGroups.add(group.getNodeValue());
- } else if (NS_LDAP.equalsIgnoreCase(ns) || NS_AD.equalsIgnoreCase(ns)) {
- try {
- policyGroups.add(new LdapName(group.getNodeValue()));
- } catch (InvalidNameException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (DOMException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- Set<Object> groupNames = new HashSet<Object>();
- for(Group groupPrincipal: groupPrincipals) {
- if(groupPrincipal instanceof LdapGroup) {
- try {
- groupNames.add(new LdapName(groupPrincipal.getName()));
- } catch (InvalidNameException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } else {
- groupNames.add(groupPrincipal.getName());
- }
- }
-
- long collectDuration = System.currentTimeMillis() - groupCollectStart;
- if(!Collections.disjoint(policyGroups, groupNames)) {
- matchedContexts.add(new Context(policy));
- System.err.println("matched on group. " + collectDuration + "ms");
- continue;
- }
- }
-
-// if(subject.getPrincipals(LdapGroupPrincipal.class).size() > 0) {
-// //todo check against ldap.
-// }
- }
+ matchedContexts.addAll(f.matchedContexts(subject, environment));
} catch (XPathExpressionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -312,7 +176,7 @@ public class Policies {
final static private Map<String, XPathExpression> commandFilterCache = new HashMap<String, XPathExpression>();
- public class Context {
+ public static class Context {
public Context(Node policy) {
super();
this.policy = policy;
@@ -504,24 +368,16 @@ public class Policies {
@Deprecated
public List<String> listAllRoles() {
List<String> results = new ArrayList<String>();
- for(Document f: aclpolicies) {
+ for(PoliciesDocument f: cache) {
try {
+ results.addAll(f.groupNames());
- NodeList groups = (NodeList) xpath.evaluate("//by/group/@ldap:name | //by/group/@name",
- f, XPathConstants.NODESET);
-
- for(int i = 0; i < groups.getLength(); i++) {
-
- String result = groups.item(i).getNodeValue();
- if(result == null || result.length() <= 0) continue;
- results.add(result);
- }
} catch (XPathExpressionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
-
+
return results;
}
}
diff --git a/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PoliciesCache.java b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PoliciesCache.java
new file mode 100644
index 0000000..0236bfa
--- /dev/null
+++ b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PoliciesCache.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2010 DTO Labs, Inc. (http://dtolabs.com)
+ *
+ * Licensed 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.
+ */
+
+/*
+* PoliciesCache.java
+*
+* User: Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+* Created: Nov 16, 2010 11:26:12 AM
+*
+*/
+package com.dtolabs.rundeck.core.authorization.providers;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * PoliciesCache retains PolicyDocument objects for inserted Files, and reloads them if file modification time changes.
+ *
+ * @author Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+ */
+public class PoliciesCache implements Iterable<PoliciesDocument> {
+ static final FilenameFilter filenameFilter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".aclpolicy");
+ }
+ };
+ private HashMap<File, PoliciesDocument> cache = new HashMap<File, PoliciesDocument>();
+ private HashMap<File, Long> expiry = new HashMap<File, Long>();
+ private DocumentBuilder builder;
+ private File rootDir;
+
+ public PoliciesCache(File rootDir) throws ParserConfigurationException {
+ this.rootDir = rootDir;
+ DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+ domFactory.setNamespaceAware(true);
+ builder = domFactory.newDocumentBuilder();
+ }
+
+ private File[] listDirFiles() {
+ return rootDir.listFiles(filenameFilter);
+ }
+
+ public synchronized void add(final File file) throws PoliciesParseException {
+ PoliciesDocument doc = getDocument(file);
+ }
+
+ private PoliciesDocument createEntry(final File file) throws PoliciesParseException {
+ try {
+ final Document document = builder.parse(file);
+ return new PoliciesDocument(document,file);
+ } catch (SAXException e) {
+ throw new PoliciesParseException(e);
+ } catch (IOException e) {
+ throw new PoliciesParseException(e);
+ }
+ }
+
+ public synchronized PoliciesDocument getDocument(final File file) throws PoliciesParseException {
+ if(!file.exists()) {
+ expiry.remove(file);
+ cache.remove(file);
+ return null;
+ }
+ final long lastmod = file.lastModified();
+ final Long cachetime = expiry.get(file);
+ final PoliciesDocument entry;
+ if (null == cachetime || lastmod > cachetime) {
+ entry = createEntry(file);
+ if (null != entry) {
+ expiry.put(file, lastmod);
+ cache.put(file, entry);
+ }
+ } else {
+ entry = cache.get(file);
+ }
+ return entry;
+ }
+
+ public Iterator<PoliciesDocument> iterator() {
+ return new cacheIterator(Arrays.asList(listDirFiles()).iterator());
+ }
+
+ /**
+ * Iterator over the PoliciesDocuments for the cache's files. It skips
+ * files that cannot be loaded.
+ */
+ private class cacheIterator implements Iterator<PoliciesDocument> {
+ Iterator<File> intIter;
+ private File nextFile;
+ private PoliciesDocument nextDocument;
+
+ public cacheIterator(final Iterator<File> intIter) {
+ this.intIter = intIter;
+ nextFile = this.intIter.hasNext() ? this.intIter.next() : null;
+ loadNextDocument();
+ }
+
+ private void loadNextDocument() {
+ while (hasNextFile() && null == nextDocument) {
+ try {
+ nextDocument = getDocument(getNextFile());
+ } catch (PoliciesParseException e) {
+
+ }
+ }
+ }
+
+ private File getNextFile() {
+ File next = nextFile;
+ nextFile = intIter.hasNext() ? intIter.next() : null;
+ return next;
+ }
+
+ private PoliciesDocument getNextDocument() {
+ PoliciesDocument doc = nextDocument;
+ nextDocument=null;
+ loadNextDocument();
+ return doc;
+ }
+
+ public boolean hasNextFile() {
+ return null != nextFile;
+ }
+
+ public boolean hasNext() {
+ return null != nextDocument;
+ }
+
+ public PoliciesDocument next() {
+ return getNextDocument();
+ }
+
+ public void remove() {
+ }
+ }
+
+}
diff --git a/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PoliciesDocument.java b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PoliciesDocument.java
new file mode 100644
index 0000000..fcabc48
--- /dev/null
+++ b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PoliciesDocument.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2010 DTO Labs, Inc. (http://dtolabs.com)
+ *
+ * Licensed 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.
+ */
+
+/*
+* PoliciesDocument.java
+*
+* User: Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+* Created: Nov 16, 2010 12:01:02 PM
+*
+*/
+package com.dtolabs.rundeck.core.authorization.providers;
+
+import com.dtolabs.rundeck.core.authentication.Group;
+import com.dtolabs.rundeck.core.authentication.LdapGroup;
+import com.dtolabs.rundeck.core.authentication.Username;
+import com.dtolabs.rundeck.core.authorization.Attribute;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.security.auth.Subject;
+import javax.xml.xpath.*;
+import javax.xml.namespace.NamespaceContext;
+import java.io.File;
+import java.util.*;
+
+
+/**
+ * PoliciesDocument wraps a Document and
+ *
+ * @author Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+ */
+public class PoliciesDocument {
+ private Document document;
+ private File file;
+ private ArrayList<String> groupNames;
+ private ArrayList<Policy> policies;
+ private Double count=null;
+ private static final XPath xpath = XPathFactory.newInstance().newXPath();
+
+ public static final XPathExpression countXpath;
+ public static final XPathExpression allPolicies;
+ public static final XPathExpression policyByUserName;
+ public static final XPathExpression policyByGroup;
+ public static final XPathExpression allGroups;
+
+ static {
+ xpath.setNamespaceContext(new NamespaceContext() {
+
+ @SuppressWarnings ("rawtypes")
+ public Iterator getPrefixes(String namespaceURI) {
+ return null;
+ }
+
+ public String getPrefix(String namespaceURI) {
+ return null;
+ }
+
+ public String getNamespaceURI(String prefix) {
+ if (prefix.equals("ldap")) {
+ return Policies.NS_LDAP;
+ } else if (prefix.equals("ActiveDirectory")) {
+ return Policies.NS_AD;
+ } else {
+ return ""; // 1.6 = XMLConstants.NULL_NS_URI;
+ }
+ }
+ });
+ try {
+ countXpath = xpath.compile("count(//policy)");
+ allPolicies = xpath.compile("//policy");
+ policyByUserName = xpath.compile("by/user/@username");
+ policyByGroup = xpath.compile("by/group/@name | by/group/@ldap:name");
+ allGroups = xpath.compile("//by/group/@name | //by/group/@ldap:name");
+ } catch (XPathExpressionException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ }
+
+ public PoliciesDocument(final Document document, final File file) {
+ this.document = document;
+ this.file=file;
+ }
+
+ public Collection<String> groupNames() throws XPathExpressionException {
+ if (null != groupNames) {
+ return groupNames;
+ }
+ groupNames = new ArrayList<String>();
+ NodeList groups = (NodeList) allGroups.evaluate(document, XPathConstants.NODESET);
+ for (int i = 0 ; i < groups.getLength() ; i++) {
+ String result = groups.item(i).getNodeValue();
+ if (result == null || result.length() <= 0) {
+ continue;
+ }
+ groupNames.add(result);
+ }
+ return groupNames;
+ }
+
+ public Double countPolicies() throws XPathExpressionException {
+ if (null != count) {
+ return count;
+ }
+ count = (Double) countXpath.evaluate(document, XPathConstants.NUMBER);
+ return count;
+ }
+
+ private Collection<Policy> listPolicies() throws XPathExpressionException {
+ if (null != policies) {
+ return policies;
+ }
+ policies = new ArrayList<Policy>();
+
+ NodeList policiesToEvaluate = (NodeList) allPolicies.evaluate(document, XPathConstants.NODESET);
+ for (int i = 0 ; i < policiesToEvaluate.getLength() ; i++) {
+
+ Node policy = policiesToEvaluate.item(i);
+ policies.add(new PolicyNode(policy));
+ }
+ return policies;
+ }
+
+ public Collection<Policies.Context> matchedContexts(Subject subject, Set<Attribute> environment) throws
+ XPathExpressionException {
+ ArrayList<Policies.Context> matchedContexts = new ArrayList<Policies.Context>();
+ int i = 0;
+ for (final Policy policy : listPolicies()) {
+
+
+ // What constitutes a match?
+ // * The username matches exactly 1 in the context.
+ // * 1 subject group matches 1 group. non disjoint sets.
+ //
+ // First match stops the search.
+
+ // TODO: time of day check.
+
+ long userMatchStart = System.currentTimeMillis();
+
+
+ Set<Username> userPrincipals = subject.getPrincipals(Username.class);
+ if (userPrincipals.size() > 0) {
+ Set<String> policyUsers = policy.getUsernames();
+ Set<String> usernamePrincipals = new HashSet<String>();
+ for (Username username : userPrincipals) {
+ usernamePrincipals.add(username.getName());
+ }
+
+ if (!Collections.disjoint(policyUsers, usernamePrincipals)) {
+ matchedContexts.add(policy.getContext());
+ System.err.println(
+ "Policy: " + i + " Matched on User: " + (System.currentTimeMillis() - userMatchStart) + "ms");
+ break;
+ }
+ }
+ System.err.println(
+ "Policy: " + i + " No match on User: " + (System.currentTimeMillis() - userMatchStart) + "ms");
+
+
+ Set<Group> groupPrincipals = subject.getPrincipals(Group.class);
+ if (groupPrincipals.size() > 0) {
+ // no username matched, check groups.
+ long groupCollectStart = System.currentTimeMillis();
+
+ Set<Object> policyGroups = policy.getGroups();
+ Set<Object> groupNames = new HashSet<Object>();
+ for (Group groupPrincipal : groupPrincipals) {
+ if (groupPrincipal instanceof LdapGroup) {
+ try {
+ groupNames.add(new LdapName(groupPrincipal.getName()));
+ } catch (InvalidNameException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } else {
+ groupNames.add(groupPrincipal.getName());
+ }
+ }
+
+ long collectDuration = System.currentTimeMillis() - groupCollectStart;
+ if (!Collections.disjoint(policyGroups, groupNames)) {
+ matchedContexts.add(policy.getContext());
+ System.err.println("matched on group. " + collectDuration + "ms");
+ continue;
+ }
+ }
+
+// if(subject.getPrincipals(LdapGroupPrincipal.class).size() > 0) {
+// //todo check against ldap.
+// }
+ i++;
+ }
+ return matchedContexts;
+ }
+
+ @Override
+ public String toString() {
+ return "PoliciesDocument{" +
+ "file=" + file +
+ '}';
+ }
+}
diff --git a/core/src/java/com/dtolabs/rundeck/core/authorization/providers/Policy.java b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/Policy.java
new file mode 100644
index 0000000..dbedb8f
--- /dev/null
+++ b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/Policy.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 DTO Labs, Inc. (http://dtolabs.com)
+ *
+ * Licensed 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.
+ */
+
+/*
+* Policy.java
+*
+* User: Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+* Created: Nov 16, 2010 12:31:26 PM
+*
+*/
+package com.dtolabs.rundeck.core.authorization.providers;
+
+import java.util.Set;
+
+/**
+ * Policy is ...
+ *
+ * @author Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+ */
+public interface Policy {
+ public Set<String> getUsernames();
+
+ Policies.Context getContext();
+
+ public Set<Object> getGroups();
+}
diff --git a/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PolicyNode.java b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PolicyNode.java
new file mode 100644
index 0000000..6b2a21b
--- /dev/null
+++ b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/PolicyNode.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2010 DTO Labs, Inc. (http://dtolabs.com)
+ *
+ * Licensed 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.
+ */
+
+/*
+* Policy.java
+*
+* User: Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+* Created: Nov 16, 2010 12:00:32 PM
+*
+*/
+package com.dtolabs.rundeck.core.authorization.providers;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.DOMException;
+
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.naming.ldap.LdapName;
+import javax.naming.InvalidNameException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * PolicyNode provides the Policy interface on top of a DOM Node
+ *
+ * @author Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+ */
+public class PolicyNode implements Policy {
+ Node policyNode;
+ HashSet<String> usernames;
+ Set<Object> groups;
+
+ public PolicyNode(Node policyNode) throws XPathExpressionException {
+ this.policyNode = policyNode;
+ init();
+ }
+
+ public Set<String> getUsernames() {
+ return usernames;
+ }
+
+ private void init() throws XPathExpressionException {
+ initUsernames();
+ initGroups();
+ }
+
+ private void initGroups() throws XPathExpressionException {
+ NodeList groupNodes = (NodeList) PoliciesDocument.policyByGroup.evaluate(policyNode, XPathConstants.NODESET);
+ groups = new HashSet<Object>(groupNodes.getLength());
+ for (int g = 0 ; g < groupNodes.getLength() ; g++) {
+ Node group = groupNodes.item(g);
+ String ns = group.getNamespaceURI();
+ if (ns == null) {
+ groups.add(group.getNodeValue());
+ } else if (Policies.NS_LDAP.equalsIgnoreCase(ns) || Policies.NS_AD.equalsIgnoreCase(ns)) {
+ try {
+ groups.add(new LdapName(group.getNodeValue()));
+ } catch (InvalidNameException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (DOMException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+
+ private void initUsernames() throws XPathExpressionException {
+
+ NodeList usernameNodes = (NodeList) PoliciesDocument.policyByUserName.evaluate(policyNode,
+ XPathConstants.NODESET);
+
+ usernames = new HashSet<String>(usernameNodes.getLength());
+ for (int u = 0 ; u < usernameNodes.getLength() ; u++) {
+ Node username = usernameNodes.item(u);
+ usernames.add(username.getNodeValue());
+ }
+ }
+
+ public Policies.Context getContext() {
+ return new Policies.Context(policyNode);
+ }
+
+ public Set<Object> getGroups() {
+ return groups;
+ }
+}
diff --git a/core/src/java/com/dtolabs/rundeck/core/authorization/providers/SAREAuthorization.java b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/SAREAuthorization.java
index 5530db4..86ab967 100644
--- a/core/src/java/com/dtolabs/rundeck/core/authorization/providers/SAREAuthorization.java
+++ b/core/src/java/com/dtolabs/rundeck/core/authorization/providers/SAREAuthorization.java
@@ -249,7 +249,6 @@ public class SAREAuthorization implements Authorization {
public Explanation explain() {
return explanation;
}
- @Override
public long evaluationDuration() {
return evaluationTime;
}
diff --git a/core/src/test/com/dtolabs/rundeck/core/authorization/providers/TestPoliciesCache.java b/core/src/test/com/dtolabs/rundeck/core/authorization/providers/TestPoliciesCache.java
new file mode 100644
index 0000000..7970c4d
--- /dev/null
+++ b/core/src/test/com/dtolabs/rundeck/core/authorization/providers/TestPoliciesCache.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010 DTO Labs, Inc. (http://dtolabs.com)
+ *
+ * Licensed 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 com.dtolabs.rundeck.core.authorization.providers;
+/*
+* TestPoliciesCache.java
+*
+* User: Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+* Created: Nov 16, 2010 1:32:37 PM
+*
+*/
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class TestPoliciesCache extends TestCase {
+ PoliciesCache policiesCache;
+
+ public TestPoliciesCache(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ return new TestSuite(TestPoliciesCache.class);
+ }
+
+
+ public void setUp() throws Exception {
+ policiesCache = new PoliciesCache(getPath("com/dtolabs/rundeck/core/authorization"));
+ }
+
+ /**
+ * @return
+ */
+ public static File getPath(String name) {
+
+ URL url = ClassLoader.getSystemResource(name);
+ File f;
+ try {
+ f = new File(url.toURI());
+ } catch (URISyntaxException e) {
+ f = new File(url.getPath());
+ }
+ return f;
+ }
+
+
+ protected void tearDown() throws Exception {
+ }
+
+ public static void main(String args[]) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+
+ public void testIterator() throws Exception {
+ final Iterator<PoliciesDocument> iterator = policiesCache.iterator();
+ assertNotNull(iterator);
+ assertTrue(iterator.hasNext());
+ ArrayList<PoliciesDocument> docs = new ArrayList<PoliciesDocument>();
+ while(iterator.hasNext()) {
+ final PoliciesDocument policiesDocument = iterator.next();
+ assertNotNull(policiesDocument);
+ docs.add(policiesDocument);
+ }
+ assertEquals(2, docs.size());
+ }
+}
\ No newline at end of file
diff --git a/core/src/test/com/dtolabs/rundeck/core/authorization/providers/TestPoliciesDocument.java b/core/src/test/com/dtolabs/rundeck/core/authorization/providers/TestPoliciesDocument.java
new file mode 100644
index 0000000..baccd88
--- /dev/null
+++ b/core/src/test/com/dtolabs/rundeck/core/authorization/providers/TestPoliciesDocument.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2010 DTO Labs, Inc. (http://dtolabs.com)
+ *
+ * Licensed 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 com.dtolabs.rundeck.core.authorization.providers;
+/*
+* TestPoliciesDocument.java
+*
+* User: Greg Schueler <a href="mailto:greg@dtosolutions.com">greg@dtosolutions.com</a>
+* Created: Nov 16, 2010 1:31:59 PM
+*
+*/
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collection;
+
+public class TestPoliciesDocument extends TestCase {
+ PoliciesDocument policiesDocument;
+ File testdir;
+ File test1;
+ File test2;
+ private DocumentBuilder builder;
+
+ public TestPoliciesDocument(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ return new TestSuite(TestPoliciesDocument.class);
+ }
+
+ public void setUp() throws Exception {
+ testdir = getPath("com/dtolabs/rundeck/core/authorization");
+ test1 = new File(testdir, "test1.aclpolicy");
+ test2 = new File(testdir, "admintest.aclpolicy");
+ DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+ domFactory.setNamespaceAware(true);
+ builder = domFactory.newDocumentBuilder();
+ }
+
+ /**
+ * @return
+ */
+ public static File getPath(String name) {
+
+ URL url = ClassLoader.getSystemResource(name);
+ File f;
+ try {
+ f = new File(url.toURI());
+ } catch (URISyntaxException e) {
+ f = new File(url.getPath());
+ }
+ return f;
+ }
+
+ protected void tearDown() throws Exception {
+ }
+
+ public static void main(String args[]) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+
+ public void testPoliciesDocument() throws Exception {
+ final Document document = builder.parse(test1);
+ PoliciesDocument doc = new PoliciesDocument(document, test1);
+ assertEquals(5.0, doc.countPolicies());
+ final Collection<String> groupNames = doc.groupNames();
+ assertEquals(6, groupNames.size());
+ }
+}
\ No newline at end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment