001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.auth.xacml; 019 020import java.io.InputStream; 021import java.net.URI; 022import java.util.HashSet; 023import java.util.Set; 024 025import javax.jcr.Node; 026import javax.jcr.PathNotFoundException; 027import javax.jcr.RepositoryException; 028import javax.jcr.Session; 029import javax.xml.parsers.DocumentBuilder; 030import javax.xml.parsers.DocumentBuilderFactory; 031 032import org.jboss.security.xacml.sunxacml.EvaluationCtx; 033import org.jboss.security.xacml.sunxacml.attr.AttributeValue; 034import org.jboss.security.xacml.sunxacml.cond.EvaluationResult; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037import org.w3c.dom.Document; 038import org.w3c.dom.Element; 039 040/** 041 * @author Gregory Jansen 042 * 043 */ 044public class PolicyUtil { 045 046 private static final Logger LOGGER = LoggerFactory.getLogger(PolicyUtil.class); 047 048 private PolicyUtil() { 049 //not called 050 } 051 052 /** 053 * Extract a policy set or policy ID for the document. 054 * 055 * @param policyStream the policy input 056 * @return an identifier 057 */ 058 public static String getID(final InputStream policyStream) { 059 try { 060 // create the factory 061 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 062 factory.setIgnoringComments(true); 063 064 factory.setNamespaceAware(true); 065 factory.setValidating(false); 066 final DocumentBuilder db = factory.newDocumentBuilder(); 067 068 // Parse the policy content 069 final Document doc = db.parse(policyStream); 070 071 final String result = getID(doc); 072 if (result == null) { 073 throw new Error("Cannot find policy ID"); 074 } 075 return result; 076 } catch (final Exception e) { 077 throw new Error("Unable to parse policy", e); 078 } 079 } 080 081 /** 082 * Get the ID of the XACML policy document. 083 * 084 * @param doc the DOM 085 * @return the ID 086 */ 087 public static String getID(final Document doc) { 088 // handle the policy, if it's a known type 089 final Element root = doc.getDocumentElement(); 090 final String name = root.getTagName(); 091 if (name.equals("Policy")) { 092 return root.getAttribute("PolicyId"); 093 } else if (name.equals("PolicySet")) { 094 return root.getAttribute("PolicySetId"); 095 } else { 096 return null; 097 } 098 } 099 100 /** 101 * Gets the repository path for a policy ID. 102 * 103 * @param id the policy id 104 * @return the repository path 105 */ 106 public static String getPathForId(final String id) { 107 return id.substring(URIConstants.POLICY_URI_PREFIX.length()); 108 } 109 110 /** 111 * Find the nearest real Modeshape node for a given Modeshape path. 112 * 113 * @param modepath the path in ModeShape 114 * @param session a session 115 * @return a Node in session 116 */ 117 public static Node getFirstRealNode(final String modepath, final Session session) { 118 LOGGER.debug("Finding firstRealNode for path: {}", modepath); 119 120 Node node = null; 121 for (String path = modepath; path.contains("/{"); path = path.substring(0, path.lastIndexOf("/{"))) { 122 try { 123 node = session.getNode(path); 124 break; 125 } catch (final PathNotFoundException expected) { 126 } catch (final RepositoryException e) { 127 throw new Error("Cannot reach repository", e); 128 } 129 } 130 if (node == null) { 131 try { 132 node = session.getRootNode(); 133 } catch (final RepositoryException e) { 134 throw new Error("Cannot reach repository", e); 135 } 136 } 137 138 LOGGER.debug("Found firstRealNode for path: {}", modepath); 139 return node; 140 } 141 142 /** 143 * Get the action ids. 144 * 145 * @param context the evaluation context 146 * @return a set of actions 147 */ 148 public static Set<String> getActions(final EvaluationCtx context) { 149 final Set<String> result = new HashSet<>(); 150 final EvaluationResult eval = 151 context.getActionAttribute(URI.create("http://www.w3.org/2001/XMLSchema#string"), 152 URIConstants.ATTRIBUTEID_ACTION_ID, null); 153 if (eval == null) { 154 return null; 155 } 156 if (eval.getStatus() == null) { 157 final AttributeValue val = eval.getAttributeValue(); 158 if (val != null && val.getValue() != null) { 159 result.add(val.getValue().toString()); 160 } 161 } 162 return result; 163 } 164}