private void loadGroups() throws PAPException { // // Create a properties object // Properties properties = new Properties(); Path file = Paths.get(this.repository.toString(), XACMLProperties.XACML_PROPERTIES_NAME); try { // // Load the properties // try (InputStream is = new FileInputStream(file.toFile())) { properties.load(is); } // // Parse it // this.groups = this.readProperties(this.repository, properties); } catch (IOException e) { logger.error("Failed to load " + file.toAbsolutePath().toString()); this.groups = new HashSet<StdPDPGroup>(); } // // Initialize the default group // PDPGroup defaultGroup = this.initializeDefaultGroup(file, properties); logger.info("Default group is: " + defaultGroup.getId() + "=" + defaultGroup.getName()); }
@Override public PDPGroup getPDPGroup(PDP pdp) throws PAPException { for (PDPGroup group : this.groups) { if (group.getPdps().contains(pdp)) { return group; } } return null; }
@Override public PDPGroup getGroup(String id) throws PAPException { for (PDPGroup g : this.groups) { if (g.getId().equals(id)) { return g; } } return null; }
@Override public PDP getPDP(String pdpId) throws PAPException { for (PDPGroup group : this.groups) { for (PDP pdp : group.getPdps()) { if (pdp.getId().equals(pdpId)) { return pdp; } } } return null; }
@Override public PDPGroup getDefaultGroup() throws PAPException { for (PDPGroup group : this.groups) { if (group.isDefaultGroup()) { return group; } } // // Default group doesn't exist // return null; }
@Override public void newPDP(String id, PDPGroup group, String name, String description) throws PAPException, NullPointerException { if (group == null) { throw new PAPException("You must specify which group the PDP will belong to."); } if (!this.groups.contains(group)) { throw new PAPException("Unknown group, not in our list."); } for (PDP p : group.getPdps()) { if (p.getId().equals(id)) { throw new PAPException("A PDP with this ID exists."); } } if (group instanceof StdPDPGroup) { StdPDP pdp = new StdPDP(id, name, description); if (((StdPDPGroup) group).addPDP(pdp)) { // // Save the properties and notify any listeners // pdpChanged(pdp); return; } } }
@Override public void removePDP(PDP pdp) throws PAPException { PDPGroup group = this.getPDPGroup(pdp); if (group == null) { throw new NullPointerException(); } if (group instanceof StdPDPGroup) { boolean result = ((StdPDPGroup) group).removePDP(pdp); if (result) { this.doSave(); } return; } String message = "Unknown PDP group class: " + group.getClass().getCanonicalName(); logger.warn(message); throw new PAPException(message); }
@Override public void SetDefaultGroup(PDPGroup group) throws PAPException { boolean changesMade = false; for (PDPGroup aGroup : groups) { if (aGroup.getId().equals(group.getId())) { if (!aGroup.isDefaultGroup()) { // TODO - since the original code checked for type we do also. if (aGroup instanceof StdPDPGroup) { ((StdPDPGroup) aGroup).setDefault(true); changesMade = true; } else { throw new IllegalArgumentException( "Group in groups of unknown type '" + aGroup.getClass().getName() + "'"); } } } else { // not the new default group if (aGroup.isDefaultGroup()) { // TODO - since the original code checked for type we do also. if (aGroup instanceof StdPDPGroup) { ((StdPDPGroup) aGroup).setDefault(false); changesMade = true; } else { throw new IllegalArgumentException( "Group in groups of unknown type '" + aGroup.getClass().getName() + "'"); } } } } if (changesMade) { this.doSave(); } }
@Override public void removePolicy(PDPPolicy policy, PDPGroup group) throws PAPException { if (group == null) { throw new NullPointerException(); } if (group instanceof StdPDPGroup && this.groups.contains(group)) { ((StdPDPGroup) group).removePolicy(policy); return; } logger.warn("unknown PDP Group: " + group); throw new PAPException("Unknown PDP Group: " + group.getId()); }
@Override public void movePDP(PDP pdp, PDPGroup newGroup) throws PAPException { if (newGroup == null) { throw new NullPointerException("You must specify which group the PDP will belong to."); } PDPGroup currentGroup = this.getPDPGroup(pdp); if (currentGroup == null) { throw new PAPException("PDP must already belong to a group."); } if (currentGroup.equals(newGroup)) { logger.warn("Already in that group."); return; } if (currentGroup instanceof StdPDPGroup && newGroup instanceof StdPDPGroup) { if (((StdPDPGroup) currentGroup).removePDP(pdp)) { boolean result = ((StdPDPGroup) newGroup).addPDP(pdp); if (result) { // // Save the configuration // this.doSave(); } else { logger.error("Failed to add to new group, putting back into original group."); if (!((StdPDPGroup) currentGroup).removePDP(pdp)) { logger.error("Failed to put PDP back into original group."); } } } } else { String message = "Unknown PDP group class: " + newGroup.getClass().getCanonicalName() + " and " + currentGroup.getClass().getCanonicalName(); logger.warn(message); throw new PAPException(message); } }
@Override public void publishPolicy( String id, String name, boolean isRoot, InputStream policy, PDPGroup group) throws PAPException { if (group == null) { throw new NullPointerException(); } if (group instanceof StdPDPGroup && this.groups.contains(group)) { ((StdPDPGroup) group).publishPolicy(id, name, isRoot, policy); return; } logger.warn("unknown PDP Group: " + group); throw new PAPException("Unknown PDP Group: " + group.getId()); }
public static void setGroupProperties(PDPGroup group, Properties properties) { // // make sure its in the list of groups // Iterable<String> groups = Splitter.on(',') .trimResults() .omitEmptyStrings() .split(properties.getProperty(PROP_PAP_GROUPS, "")); boolean inList = false; for (String g : groups) { if (g.equals(group.getId())) { inList = true; } } if (!inList) { Set<String> grps = Sets.newHashSet(groups); grps.add(group.getId()); String newGroupList = ""; if (grps.size() == 1) { newGroupList = grps.iterator().next(); } else if (grps.size() > 1) { newGroupList = Joiner.on(',').skipNulls().join(grps); } logger.info("New Group List: " + newGroupList); properties.setProperty(PROP_PAP_GROUPS, newGroupList); } // // Set its properties // properties.setProperty(group.getId() + ".name", group.getName()); properties.setProperty(group.getId() + ".description", group.getDescription()); // // Set its PDP list // if (group.getPdps().size() > 0) { String pdpList = ""; if (group.getPdps().size() == 1) { pdpList = group.getPdps().iterator().next().getId(); } else if (group.getPdps().size() > 1) { Set<String> ids = new HashSet<String>(); for (PDP pdp : group.getPdps()) { ids.add(pdp.getId()); } pdpList = Joiner.on(',').skipNulls().join(ids); } properties.setProperty(group.getId() + ".pdps", pdpList); } else { properties.setProperty(group.getId() + ".pdps", ""); } }
private void saveConfiguration() throws PAPException, IOException { // // Create our properties object // Properties properties = new Properties() { private static final long serialVersionUID = 1L; // For Debugging it is helpful for the file to be in a sorted order, // any by returning the keys in the natural Alpha order for strings we get close enough. // TreeSet is sorted, and this just overrides the normal Properties method to get the // keys. @Override public synchronized Enumeration<Object> keys() { return Collections.enumeration(new TreeSet<Object>(super.keySet())); } }; // // Iterate our groups // List<String> ids = new ArrayList<String>(); for (PDPGroup group : this.groups) { ids.add(group.getId()); properties.setProperty( group.getId() + ".name", (group.getName() == null ? "" : group.getName())); properties.setProperty( group.getId() + ".description", (group.getDescription() == null ? "" : group.getDescription())); // // Iterate its PDPs // List<String> pdps = new ArrayList<String>(); for (PDP pdp : group.getPdps()) { pdps.add(pdp.getId()); properties.setProperty(pdp.getId() + ".name", (pdp.getName() == null ? "" : pdp.getName())); properties.setProperty( pdp.getId() + ".description", (pdp.getDescription() == null ? "" : pdp.getDescription())); } String pdpList = ""; if (pdps.size() == 1) { pdpList = pdps.get(0); } else if (pdps.size() > 1) { pdpList = Joiner.on(',').skipNulls().join(pdps); } if (logger.isDebugEnabled()) { logger.debug("Group " + group.getId() + " PDPS: " + pdpList); } properties.setProperty(group.getId() + ".pdps", pdpList); } if (ids.isEmpty()) { throw new PAPException("Inconsistency - we have NO groups. We should have at least one."); } String groupList = ""; if (ids.size() == 1) { groupList = ids.get(0); } else if (ids.size() > 1) { groupList = Joiner.on(',').skipNulls().join(ids); } logger.info("New Group List: " + groupList); properties.setProperty(PROP_PAP_GROUPS, groupList); // // Get the default group // PDPGroup defaultGroup = this.getDefaultGroup(); if (defaultGroup == null) { throw new PAPException("Invalid state - no default group."); } properties.setProperty(PROP_PAP_GROUPS_DEFAULT, defaultGroup.getId()); // // Now we can save the file // Path file = Paths.get(this.repository.toString(), "xacml.properties"); try (OutputStream os = Files.newOutputStream(file)) { properties.store(os, ""); } }
@Override public void removeGroup(PDPGroup group, PDPGroup newGroup) throws PAPException, NullPointerException { if (group == null) { throw new NullPointerException(); } // // Does this group exist? // if (!this.groups.contains(group)) { logger.error("This group doesn't exist."); throw new PAPException("The group '" + group.getId() + "' does not exist"); } // // Is it the default group? // if (group.isDefaultGroup()) { throw new PAPException("You cannot delete the default group."); } Set<PDP> pdps = group.getPdps(); // // Are there PDPs? If so, then we need a target group // if (!pdps.isEmpty() && newGroup == null) { throw new NullPointerException( "Group targeted for deletion has PDPs, you must provide a new group for them."); } // // Move the PDPs // if (!pdps.isEmpty()) { if (!(newGroup instanceof StdPDPGroup)) { throw new PAPException( "Unexpected class for newGroup: " + newGroup.getClass().getCanonicalName()); } // The movePDP function will modify the set of PDPs in the group. // To avoid concurrent modification exceptions we need to duplicate the list before calling // that // function. List<PDP> pdpList = new ArrayList<PDP>(); for (PDP pdp : pdps) { pdpList.add(pdp); } // now we can use the PDPs from the list without having ConcurrentAccessExceptions for (PDP pdp : pdpList) { this.movePDP(pdp, newGroup); } } // // remove the directory for the group // String id = group.getId(); Path groupPath = Paths.get(this.repository.toString(), id); // // If it exists already // if (!Files.exists(groupPath)) { logger.warn("removeGroup " + id + " directory does not exist" + groupPath.toString()); } else { try { Files.walkFileTree( groupPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return super.visitFile(file, attrs); } }); // // delete the directory // Files.delete(groupPath); } catch (IOException e) { logger.error("Failed to delete " + groupPath + ": " + e); throw new PAPException("Failed to delete " + id); } } // remove the group from the set of all groups groups.remove(group); // // Save changes // changed(); this.doSave(); }
@Override public void updateGroup(PDPGroup group) throws PAPException { if (group == null || group.getId() == null) { throw new PAPException("Group or id is null"); } if (group.getName() == null || group.getName().trim().length() == 0) { throw new PAPException("New name for group cannot be null or blank"); } StdPDPGroup existingGroup = (StdPDPGroup) getGroup(group.getId()); if (existingGroup == null) { throw new PAPException("Update found no existing group with id '" + group.getId() + "'"); } // We do dramatically different things when the Name changes // because the Name is essentially the identity of the group (as the User knows it) so when the // Identity changes we have to change the group ID. if (group.getName().equals(existingGroup.getName())) { // update the disk try { ((StdPDPGroup) group).saveGroupConfiguration(); } catch (IOException e) { throw new PAPException( "Unable to save new configuration for '" + group.getName() + "': " + e.getMessage()); } // update the group in the set by simply replacing the old instance with the new one this.groups.remove(existingGroup); this.groups.add((StdPDPGroup) group); } else { // the name/identity of the group has changed // generate the new id String newId = createNewPDPGroupId(group.getName()); // make sure no other group uses the new id for (PDPGroup g : groups) { if (g.getId().equals(newId)) { throw new PAPException( "Replacement name maps to ID '" + newId + "' which is already in use"); } } ((StdPDPGroup) group).setId(newId); // rename the existing directory to the new id Path oldPath = existingGroup.getDirectory(); Path newPath = Paths.get(oldPath.getParent().toString(), newId); ((StdPDPGroup) group).setDirectory(newPath); try { boolean success = oldPath.toFile().renameTo(newPath.toFile()); if (!success) { throw new PAPException("Unable to rename directory; reason unknown"); } } catch (Exception e) { logger.error("Move '" + oldPath + "' to '" + newPath + "': " + e.getMessage(), e); throw new PAPException( "Unable to move directory from '" + oldPath + "' to '" + newPath + "': " + e.getMessage()); } // update the disk try { ((StdPDPGroup) group).saveGroupConfiguration(); } catch (IOException e) { throw new PAPException( "Unable to save new configuration for '" + group.getName() + "': " + e.getMessage()); } // save the new group into the Set groups.remove(existingGroup); groups.add((StdPDPGroup) group); } // perhaps only the group changed, but if the name/id changed it may look to a listener like // more than // one group changed(); }
@Override public void newGroup(String name, String description) throws PAPException, NullPointerException { // // Null check // if (name == null) { throw new NullPointerException(); } // // Do we already have this group? // for (PDPGroup group : this.groups) { if (group.getName().equals(name)) { throw new PAPException("Group with this name=" + name + " already exists."); } } // create an Id that can be used as a file name and a properties file key. // Ids must not contain \/:*?"<>|=,; // The ID must also be unique within the current set of PDPGroups. String id = createNewPDPGroupId(name); // // Construct the directory path // Path groupPath = Paths.get(this.repository.toString(), id); // // If it exists already // if (Files.exists(groupPath)) { logger.warn("addGroup " + id + " directory exists" + groupPath.toString()); } else { try { // // Create the directory // Files.createDirectory(groupPath); } catch (IOException e) { logger.error("Failed to create " + groupPath); throw new PAPException("Failed to create " + id); } } // // Create the Policies // Path policyProperties = Paths.get(groupPath.toString(), "xacml.policy.properties"); if (Files.exists(policyProperties)) { logger.warn("addGroup " + id + " file exists: " + policyProperties.toString()); } else { Properties props = new Properties(); props.setProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, ""); props.setProperty(XACMLProperties.PROP_ROOTPOLICIES, ""); try { Files.createFile(policyProperties); try (OutputStream os = Files.newOutputStream(policyProperties)) { props.store(os, ""); } } catch (IOException e) { logger.error("Failed to create " + policyProperties); throw new PAPException("Failed to create " + id); } } // // Create the PIP config // Path pipProperties = Paths.get(groupPath.toString(), "xacml.pip.properties"); if (Files.exists(pipProperties)) { logger.warn("addGroup " + id + " file exists: " + pipProperties.toString()); } else { try { Properties props = new Properties(); props.setProperty(XACMLProperties.PROP_PIP_ENGINES, ""); Files.createFile(pipProperties); try (OutputStream os = Files.newOutputStream(pipProperties)) { props.store(os, ""); } } catch (IOException e) { logger.error("Failed to create " + pipProperties); throw new PAPException("Failed to create " + id); } } // // Ok now add it // StdPDPGroup newGroup = new StdPDPGroup(id, name, description, groupPath); if (this.groups.add(newGroup)) { // save the new group in our properties and notify any listeners of the change groupChanged(newGroup); } }