Class SimpleACIWorld
Representation of all the ACI for the whole DIT using a much simplified model compared to ACIWorld. The simplifications are made by imposing certain restrictions. By making these restrictions it is possible to combine different rules without having one rule clash with another rule unexpectedly.
ACI rule information is split up differently compared to how it is handled in ACIWorld or in the BER. It is split into "roles" (which contain auth-level and user info), "rules" (which contain grant/deny, permission bits, protected items, objectclass refinements and so on) and "areas" (which contain lists of region specifications based on base/min/max/chops info). An ACI "item" combines a role, a rule and an area with a precedence.
These are the restrictions imposed to permit the simplifications:
- SAC (Simple Access Control) areas are used by default. With SAC, it isn't necessary to worry about ACIAs or entryACI. Everything is controlled by the prescriptive ACI on the ACSA, and the complete set of rules can be visualised by the user in any GUI built on top of SimpleACIWorld. For SAC, subentry ACI is completely independent from prescriptive ACI. However for BAC with ACIA admin points, subentry ACI on the ACIA is affected by superior prescriptive ACI. So for simplicity, BAC regions and ACIAs are not directly supported by this class. However, if the user chooses to switch the ACSA to BAC, the top-level prescriptive ACI and subentry ACI is handled as for SAC, and any ACI encoded in entry ACI or ACIA prescriptive ACI is left alone. Since entry ACI and prescriptive ACI on ACIAs is invisible to this class, and may override the rules defined here, warnings are given if ACIAs or BAC regions are detected.
- Deny rules must always apply to all users and for all bind levels. This simplifies the way that different preset rules work together, allowing different rules to be combined without unexpected consequences. Note that grant rules just add up, so don't need differentiation by precedence. Precedence is only necessary when deny rules are introduced. So we get the user to order the grant rules using the precedences, and then insert the deny rules at a precedence level that gives the effect that they are looking for.
- Deny rules can never have the same precedence as grant rules. This is because more-specific grant rules will override a deny at the same precedence, which makes the effect non-obvious to the user when the precise rules are hidden away behind descriptive titles. It is suggested that grants be given even precedences (e.g. 10,20,30), and denies be given odd precedences (e.g. 15,25,35) to avoid problems.
- EntryACI on the ACSA or subentries is not accepted, causing the region to be treated as 'local' (i.e. not part of the 'global' ACI controlled by this class), even if entry ACI may be tolerated otherwise when in BAC mode. This is because it will be overwritten when temporary entryACI is written as part of the process of saving the ACI rules.
- A rule that specifies 'user_entry' (i.e. that the rule only applies to entries whose DN matches the user's bound DN) can only be used in combination with a role that specifies 'user_all'. This is due to the way that the low-level ACI represents this scenario as a user filter rather than an entry filter.
- There are also restrictions from ACIWorld, for example: all deny rules must be separate from grant rules, and entry-protection rule tuples must be separate from attribute-protection rule tuples. All the other limitations and simplifications documented in ACITuple/ACIWorld also apply.
This is how the simple ACI objects are linked up: SimpleACIWorld -> SimpleACIItem -> { SimpleACIRole, SimpleACIArea[.Region], SimpleACIRule[.Tuple] }.
Role and rule name hashes are stored in the low-level ACI tuple names on the directory to help them be recovered on reloading from a live DIT. The full specification of the roles and rules is stored in a compressed blob of XML data in a subentry below each ACSA in order to allow the original role and rule names to be recovered, along with any roles or rules which were defined but unused. In addition, a blob of subentry ACI and subtree specifications is stored for subentry ACI rules to ensure that it is always possible to recover the original area information configured by the user.
The fields of this class may be accessed directly. There are also methods available to simplify access to some of the fields.
- Since:
- 15.0
- Author:
- jp
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic class
ACSA: Access Control Specific Area.static interface
Interface of code that filters a list of ACSA DNs down to the set that should be loaded up.static class
List of ACSAs.static class
Error or warning message, with attached DN and/or exception. -
Field Summary
FieldsModifier and TypeFieldDescriptionfinal SimpleACIWorld.ACSAList
List of all ACSAs loaded, including global, local and removed ones.final IsodeDirectorySession
Directory session to use, or null if this is not connected to a directory.static final AttributeValue
Special subentryACI value that has no significant effect but is used to mark admin points that should be treated as 'local', i.e.static final AttributeValue
Special subentryACI value that has no significant effect but is used to mark admin points that are part of the scope of SimpleACIWorld.final List<SimpleACIItem>
List of active items combining roles and rules.final List<SimpleACIRole>
List of roles.static final DN
DN of ACSA that acts as a proxy for the root ACSA on D3.final List<SimpleACIRule>
List of rules. -
Constructor Summary
ConstructorsConstructorDescriptionSimpleACIWorld
(IsodeDirectorySession ds, DN base) Construct a SimpleACIWorld for the given directory session and base-DN. -
Method Summary
Modifier and TypeMethodDescriptionvoid
addACIItem
(int precedence, SimpleACIRole role, SimpleACIRule rule, SimpleACIArea area) Create a new ACI item, and add it to the list of items.Add a new ACSA, using SAC (Simple Access Control).Add a new ACSA, using SAC or BAC according to the isBAC argument.Add a new ACSA or AAP, using SAC or BAC according to the isBAC argument.addRole
(SimpleACIRole role) Add a new role to the SimpleACIWorld, checking to see if it is already present with the same name (identical role), or if the name is already taken for another role (non-identical).addRule
(SimpleACIRule rule) Add a new rule to the SimpleACIWorld, checking to see if it is already present with the same name (identical rule), or if the name is already taken for another rule (non-identical).void
Scan the 'items' list, and pick up any new roles or rules which aren't already in the 'roles' or 'rules' lists, and add them (usingaddRole(com.isode.dsapi.aci.SimpleACIRole)
oraddRule(com.isode.dsapi.aci.SimpleACIRule)
to ensure that identical copies are merged).dump()
Return a debug dump of the entire ACI world data structures.void
Dump out all errors and warnings using logger.warning().boolean
Test whether the contents of two SimpleACIWorld instances are the same.void
filterToACSAAboveAndPathTo
(DN target_dn) Set the ACSA filter to look for the nearest enclosing ACSA for the given DN, and then to filter the ACSAs to just that ACSA and the ACSA at the DN itself, if it exists.static List<AttributeValue>
generateBootstrapACI
(DN user_dn) Generate bootstrap ACI which can be used for entryACI or subentryACI attributes.static List<AttributeValue>
generateBootstrapACI
(DN user_dn, String name1, String name2) Generate bootstrap ACI which can be used for entryACI or subentryACI attributes.Return the ACSA object corresponding to the given DN, or null if it is not found.getBase()
Return the base-DN used by the most recent load().getDupRole
(SimpleACIRole excl, String name) Look for a role that has the given name but isn't the one passed.getDupRule
(SimpleACIRule excl, String name) Look for a rule that has the given name but isn't the one passed.Returns the list of errors reported by the previous save() or load() call.int
Return a list of unused roles, that is those not referenced by any item.Return a list of unused rules, that is those not referenced by any item.Returns the list of warnings reported by the previous save() or load() call, plus warnings generated by checks on the current state of the loaded data (which are regenerated each call).int
hashCode()
Hash code.void
ignoreACSA
(DN dn) Tell the SimpleACIWorld to treat the ACSA at the given DN as 'local', which means that it will ignore it and not update it when save() is called.void
load()
Load up all the ACI information from the directory, clearing any currently loaded data.boolean
Load up ACI data from the directory, usingload()
.int
Load up the ACI information from the directory and calculate a hash from it.static SimpleACIWorld
Load up a SimpleACIWorld from the given file.void
Clear all prescriptive ACSA information from the admin point on next .save(), but leave it with bootstrap ACI and flagged as a local ACSA (i.e.void
Check that the given role's name is unique, and if it isn't, add a number to the name to make it unique.void
Check that the given rule's name is unique, and if it isn't, add a number to the name to make it unique.void
Relocate all the areas of the DIT according to the list of source/target DNs provided.void
removeACSA
(DN dn) Remove the ACSA from the directory completely.void
removeItemsWithPrecedence
(int prec) Remove all the items with the given precedence number.void
removeUsersAndGroups
(List<DN> dnlist) Remove all mentions of the given user and/or group DNs from the roles.void
replaceRole
(SimpleACIRole old_role, SimpleACIRole new_role) Replace one role with another role.void
replaceRule
(SimpleACIRule old_rule, SimpleACIRule new_rule) Replace one rule with another rule.void
save()
Write back all the ACI to the directory, in all the appropriate places.boolean
Write back all the ACI to the directory, usingsave()
.void
Set the ACSA filter, which selects which ACSAs to load and may modify the base DN.void
setACSAIgnoreList
(List<DN> acsa_ignore) Set the list of DNs that should be specifically ignored and treated as 'local'.void
sort()
Sort roles, rules, items and ACSAs according to their sort orders.toString()
Debugging dump.void
writeACSASummary
(String fnam) Write a summary of the current ACSA settings to the given file.void
Write the items, roles and rules to the given XML file.
-
Field Details
-
ds
Directory session to use, or null if this is not connected to a directory. -
acsas
List of all ACSAs loaded, including global, local and removed ones. -
roles
List of roles. -
rules
List of rules. -
items
List of active items combining roles and rules. -
root_proxy_acsa
DN of ACSA that acts as a proxy for the root ACSA on D3. -
gac_true_av
Special subentryACI value that has no significant effect but is used to mark admin points that are part of the scope of SimpleACIWorld. The rule name is "GlobalAccessControl: true". -
gac_false_av
Special subentryACI value that has no significant effect but is used to mark admin points that should be treated as 'local', i.e. outside of the scope of SimpleACIWorld. The rule name is "GlobalAccessControl: false".
-
-
Constructor Details
-
SimpleACIWorld
Construct a SimpleACIWorld for the given directory session and base-DN.- Parameters:
ds
- IsodeDirectorySession to use to access and modify directory, or null if this is an offline SimpleACIWorldbase
- Base DN of subtree that will be searched for ACSAs: normally the root DN- Throws:
BadAttributeTypeException
- in the case of attribute types being missing from schema.
-
-
Method Details
-
setACSAIgnoreList
Set the list of DNs that should be specifically ignored and treated as 'local'. -
setACSAFilter
Set the ACSA filter, which selects which ACSAs to load and may modify the base DN. SeeSimpleACIWorld.ACSAFilter
.- Parameters:
filter
- ACSAFilter, or null if no filter is required
-
filterToACSAAboveAndPathTo
Set the ACSA filter to look for the nearest enclosing ACSA for the given DN, and then to filter the ACSAs to just that ACSA and the ACSA at the DN itself, if it exists. This is a suitable set of ACSAs to add/remove the ACSA flags on the given DN.- Parameters:
target_dn
- Starting-point DN
-
getBase
Return the base-DN used by the most recent load().- Returns:
- Base DN
-
relocate
Relocate all the areas of the DIT according to the list of source/target DNs provided. The logical process for relocating a given DN is to go through the 'reloc_arr' and find the first source/target pair where the DN is within the source subtree. The DN is then relocated according to that pair. If the DN does not match any source/target pair, then it is not relocated.Both the item-areas and role-DNs are relocated according to 'reloc_arr'. Where subtrees are moved from one location to another, the old area reverts to whatever the parent-defined behaviour is (for a miscellaneous subtree at that level), rather than being excluded and chopped out entirely.
- Parameters:
reloc_arr
- Array containing an even number of DNs organized into pairs of DNs: a source DN and a target DN. Each source/target pair specify a subtree relocation, and they are searched in the order given. The first match found defines the relocation for any given DN.
-
load
Load up all the ACI information from the directory, clearing any currently loaded data. This does directory operations, so must be called from a BackgroundTask. Warnings may be generated, which can be fetched withgetWarnings()
.- Throws:
OperationFailedException
- in case of any errors. The list of errors can be fetched withgetErrors()
.
-
loadBERHash
Load up the ACI information from the directory and calculate a hash from it. The data is not decoded, so the SimpleACIWorld remains empty. This call is very much faster than the normalload()
call. This does directory operations, so must be called from a BackgroundTask. Warnings may be generated, which can be fetched withgetWarnings()
.- Returns:
- Hash code of data loaded, which is the same value that
can be fetched using
getLastBERHash()
- Throws:
OperationFailedException
- in case of any errors. The list of errors can be fetched withgetErrors()
.
-
getLastBERHash
public int getLastBERHash()Get the hash value calculated by the last successfulload()
,loadBERHash()
orsave()
operation. This hash value incorporates data from all the GLOBAL ACI BER saved to the DSA and also the ACSA-related flags from all areas on the DIT. It is only sensitive to changes in the higher-level roles and rules where they change the tuple BER, or where there are role/rule name changes (as the name hashes are included in the tuple name). Addition or deletion of unused roles or rules will not cause a change in this hash value.The intention is that the caller should get an identical hash value for loading data back from the DSA as they got for saving it. This may be used to check for changes on the DSA.
-
writeACSASummary
Write a summary of the current ACSA settings to the given file.- Parameters:
fnam
- File to write settings to.- Throws:
IOException
- In case of I/O problem
-
writeXML
Write the items, roles and rules to the given XML file. This dump is intended to record the logical global ACI view, without worrying about the details of the ACSAs beneath it, so no ACSA information is included in the XML. However ACSA information is dumped as comments to aid debugging remote configurations.- Parameters:
filename
- Path of file to write- Throws:
IOException
- In case of I/O problem
-
loadXML
Load up a SimpleACIWorld from the given file. In the case of loading errors, dumps messages to the Isode logs as warnings and returns null. -
addACIItem
Create a new ACI item, and add it to the list of items. This is a convenience method, as the same can be achieved by adding toitems
directly.- Parameters:
precedence
- Precedence of item, from 0 (lowest) to 255 (highest)role
- SimpleACIRole, or null for denyrule
- SimpleACIRulearea
- SimpleACIArea
-
save
Write back all the ACI to the directory, in all the appropriate places. All the ACSAs that are marked as 'global' have their ACI written. Those marked as 'local' are ignored. The original rule and role definitions are saved as a blob as an extra subentry under each ACSA. That allows the full names and default precedences, etc to be recovered.This method performs directory operations and must be called from a BackgroundTask. All the relevant entries are rewritten whether they need it or not.
- Throws:
OperationFailedException
- in case of any errors. The list of errors can be fetched withgetErrors()
.
-
generateBootstrapACI
Generate bootstrap ACI which can be used for entryACI or subentryACI attributes. Uses default rule names.- Parameters:
user_dn
- DN of user who will be given permissions- Returns:
- List
-
generateBootstrapACI
Generate bootstrap ACI which can be used for entryACI or subentryACI attributes.- Parameters:
user_dn
- DN of user who will be given permissionsname1
- Name to use for entry ACI rule, or null for defaultname2
- Name to use for attribute ACI rule, or null for default- Returns:
- List
-
addACSA
Add a new ACSA or AAP, using SAC or BAC according to the isBAC argument. The SimpleACIWorld code will make the given entry into an admin point (if it isn't already) and add ACSA, optional AAP and SAC/BAC flags when .save() is called. This call makes no changes to the ACI items or rules that are already present in the SimpleACIWorld. The new ACSA will automatically pick up whatever ACI was already applying to the region according to the current set of items.This call may also be used to turn a local ACSA into a global one. The previously local ACSA will get the ACI rules that have been set to apply to the area it covers, ignoring whatever ACI rules it currently has. Note that the user should check that this is what they want, as the loading code has to guess what is most likely to be the intention of the rules for a local ACSA area, since it can't load up any ACI from it.
- Parameters:
dn
- ACSA base DNisBAC
- 'true' for BAC, 'false' for SAC (preferred)isAAP
- 'true' for AAP, 'false' for plain ACSA- Returns:
- ACSA that was added or updated
-
addACSA
Add a new ACSA, using SAC or BAC according to the isBAC argument. The SimpleACIWorld code will make the given entry into an admin point (if it isn't already) and add ACSA and SAC/BAC flags when .save() is called. This call makes no changes to the ACI items or rules that are already present in the SimpleACIWorld. The new ACSA will automatically pick up whatever ACI was already applying to the region according to the current set of items.This call may also be used to turn a local ACSA into a global one. The previously local ACSA will get the ACI rules that have been set to apply to the area it covers, ignoring whatever ACI rules it currently has. Note that the user should check that this is what they want, as the loading code has to guess what is most likely to be the intention of the rules for a local ACSA area, since it can't load up any ACI from it.
- Parameters:
dn
- ACSA base DNisBAC
- 'true' for BAC, 'false' for SAC (preferred)- Returns:
- ACSA that was added or updated
-
addACSA
Add a new ACSA, using SAC (Simple Access Control). The SimpleACIWorld code will make the given entry into an admin point (if it isn't already) and add ACSA and SAC flags when .save() is called. This call makes no changes to the ACI items or rules that are already present in the SimpleACIWorld. The new ACSA will automatically pick up whatever ACI was already applying to the region according to the current set of items.This call may also be used to turn a local ACSA into a global one. The previously local ACSA will get the ACI rules that have been set to apply to the area it covers, ignoring whatever ACI rules it currently has. Note that the user should check that this is what they want, as the loading code has to guess what is most likely to be the intention of the rules for a local ACSA area, since it can't load up any ACI from it.
- Parameters:
dn
- ACSA base DN- Returns:
- ACSA that was added or updated
-
removeACSA
Remove the ACSA from the directory completely. On .save(), all ACI-related attributes and roles will be cleared from the admin point and its subentries. If there are no roles left in the admin point, then the admin point is also removed, leaving a normal entry. The ACI that would have been installed in that ACSA will now be installed into the superior ACSA instead. See alsolocalACSA(com.isode.dsapi.DN)
.- Parameters:
dn
- ACSA base DN
-
localACSA
Clear all prescriptive ACSA information from the admin point on next .save(), but leave it with bootstrap ACI and flagged as a local ACSA (i.e. with GAC flag of 'false'). See alsoremoveACSA(com.isode.dsapi.DN)
.- Parameters:
dn
- ACSA base DN
-
ignoreACSA
Tell the SimpleACIWorld to treat the ACSA at the given DN as 'local', which means that it will ignore it and not update it when save() is called.- Parameters:
dn
- ACSA base DN
-
getACSA
Return the ACSA object corresponding to the given DN, or null if it is not found.- Parameters:
dn
- DN of ACSA object to search for- Returns:
- ACSA, or null if not found
-
correctLists
public void correctLists()Scan the 'items' list, and pick up any new roles or rules which aren't already in the 'roles' or 'rules' lists, and add them (usingaddRole(com.isode.dsapi.aci.SimpleACIRole)
oraddRule(com.isode.dsapi.aci.SimpleACIRule)
to ensure that identical copies are merged). This makes sure that everything is sane, even if the caller hasn't been updating the 'roles' and 'rules' lists. This also sorts the items, roles and rules into order, and renames roles or rules that have the same name. This is called automatically on saving. -
loadAndLogErrors
public boolean loadAndLogErrors()Load up ACI data from the directory, usingload()
. If there are any errors, log them as warnings using Logger, and return false. Otherwise return true.- Returns:
- false: warnings, true: success
-
saveAndLogErrors
public boolean saveAndLogErrors()Write back all the ACI to the directory, usingsave()
. If there are any errors, log them as warnings with Logger and return false. Otherwise return true.- Returns:
- false: errors, true: success
-
dumpWarningsToLog
public void dumpWarningsToLog()Dump out all errors and warnings using logger.warning(). -
getErrors
Returns the list of errors reported by the previous save() or load() call. Each is a DNMessage with message text, and possibly an attached exception as a cause.- Returns:
- List
-
getWarnings
Returns the list of warnings reported by the previous save() or load() call, plus warnings generated by checks on the current state of the loaded data (which are regenerated each call). Each is a DNMessage with message text, and possibly an attached exception as a cause.- Returns:
- List
-
replaceRole
Replace one role with another role. Updates all the SimpleACIItem instances that refer to the old role to refer to the new one. Makes the new role name unique. -
replaceRule
Replace one rule with another rule. Updates all the SimpleACIItem instances that refer to the old rule to refer to the new one. Makes the new rule name unique. -
getDupRole
Look for a role that has the given name but isn't the one passed. This is to check for duplicates.- Parameters:
excl
- Role to exclude from searchname
- Name to look for- Returns:
- SimpleACIRole if found, else null
-
getDupRule
Look for a rule that has the given name but isn't the one passed. This is to check for duplicates.- Parameters:
excl
- Rule to exclude from searchname
- Name to look for- Returns:
- SimpleACIRule if found, else null
-
makeRoleNameUnique
Check that the given role's name is unique, and if it isn't, add a number to the name to make it unique.- Parameters:
role
- SimpleACIRole to check
-
makeRuleNameUnique
Check that the given rule's name is unique, and if it isn't, add a number to the name to make it unique.- Parameters:
rule
- SimpleACIRule to check
-
addRole
Add a new role to the SimpleACIWorld, checking to see if it is already present with the same name (identical role), or if the name is already taken for another role (non-identical). If the role is already present, then a reference to the existing copy is returned. If the name is already taken, then a new name is generated for the added role. Otherwise the role is simply added. -
addRule
Add a new rule to the SimpleACIWorld, checking to see if it is already present with the same name (identical rule), or if the name is already taken for another rule (non-identical). If the rule is already present, then a reference to the existing copy is returned. If the name is already taken, then a new name is generated for the added rule. Otherwise the rule is simply added. -
getUnusedRoles
Return a list of unused roles, that is those not referenced by any item.- Returns:
- List
-
getUnusedRules
Return a list of unused rules, that is those not referenced by any item.- Returns:
- List
-
removeItemsWithPrecedence
public void removeItemsWithPrecedence(int prec) Remove all the items with the given precedence number. This is used to support deselecting rule-items in the DSASetup.- Parameters:
prec
- Precedence
-
removeUsersAndGroups
Remove all mentions of the given user and/or group DNs from the roles. Where a role is left empty, it is deleted, along with any items that depend on it. This is used to strip unwanted groups out of a GAC config by DSASetup.- Parameters:
dnlist
- List of DNs to delete (not null)
-
sort
public void sort()Sort roles, rules, items and ACSAs according to their sort orders. Roles and rules are sorted according to their label, and items are sorted by precedence, grant/deny, role and rule. ACSAs are sorted by DN. -
equals
Test whether the contents of two SimpleACIWorld instances are the same. This forces all internal lists in all the objects to be sorted. -
hashCode
public int hashCode()Hash code. Forces everything to be sorted. -
dump
Return a debug dump of the entire ACI world data structures.- Returns:
- Debug dump string
-
toString
Debugging dump.
-