Search in sources :

Example 1 with AclEntryScope

use of org.apache.hadoop.fs.permission.AclEntryScope in project hadoop by apache.

the class AclTransformation method filterAclEntriesByAclSpec.

/**
   * Filters (discards) any existing ACL entries that have the same scope, type
   * and name of any entry in the ACL spec.  If necessary, recalculates the mask
   * entries.  If necessary, default entries may be inferred by copying the
   * permissions of the corresponding access entries.  It is invalid to request
   * removal of the mask entry from an ACL that would otherwise require a mask
   * entry, due to existing named entries or an unnamed group entry.
   *
   * @param existingAcl List<AclEntry> existing ACL
   * @param inAclSpec List<AclEntry> ACL spec describing entries to filter
   * @return List<AclEntry> new ACL
   * @throws AclException if validation fails
   */
public static List<AclEntry> filterAclEntriesByAclSpec(List<AclEntry> existingAcl, List<AclEntry> inAclSpec) throws AclException {
    ValidatedAclSpec aclSpec = new ValidatedAclSpec(inAclSpec);
    ArrayList<AclEntry> aclBuilder = Lists.newArrayListWithCapacity(MAX_ENTRIES);
    EnumMap<AclEntryScope, AclEntry> providedMask = Maps.newEnumMap(AclEntryScope.class);
    EnumSet<AclEntryScope> maskDirty = EnumSet.noneOf(AclEntryScope.class);
    EnumSet<AclEntryScope> scopeDirty = EnumSet.noneOf(AclEntryScope.class);
    for (AclEntry existingEntry : existingAcl) {
        if (aclSpec.containsKey(existingEntry)) {
            scopeDirty.add(existingEntry.getScope());
            if (existingEntry.getType() == MASK) {
                maskDirty.add(existingEntry.getScope());
            }
        } else {
            if (existingEntry.getType() == MASK) {
                providedMask.put(existingEntry.getScope(), existingEntry);
            } else {
                aclBuilder.add(existingEntry);
            }
        }
    }
    copyDefaultsIfNeeded(aclBuilder);
    calculateMasks(aclBuilder, providedMask, maskDirty, scopeDirty);
    return buildAndValidateAcl(aclBuilder);
}
Also used : AclEntryScope(org.apache.hadoop.fs.permission.AclEntryScope) AclEntry(org.apache.hadoop.fs.permission.AclEntry)

Example 2 with AclEntryScope

use of org.apache.hadoop.fs.permission.AclEntryScope in project hadoop by apache.

the class AclTransformation method calculateMasks.

/**
   * Calculates mask entries required for the ACL.  Mask calculation is performed
   * separately for each scope: access and default.  This method is responsible
   * for handling the following cases of mask calculation:
   * 1. Throws an exception if the caller attempts to remove the mask entry of an
   *   existing ACL that requires it.  If the ACL has any named entries, then a
   *   mask entry is required.
   * 2. If the caller supplied a mask in the ACL spec, use it.
   * 3. If the caller did not supply a mask, but there are ACL entry changes in
   *   this scope, then automatically calculate a new mask.  The permissions of
   *   the new mask are the union of the permissions on the group entry and all
   *   named entries.
   *
   * @param aclBuilder ArrayList<AclEntry> containing entries to build
   * @param providedMask EnumMap<AclEntryScope, AclEntry> mapping each scope to
   *   the mask entry that was provided for that scope (if provided)
   * @param maskDirty EnumSet<AclEntryScope> which contains a scope if the mask
   *   entry is dirty (added or deleted) in that scope
   * @param scopeDirty EnumSet<AclEntryScope> which contains a scope if any entry
   *   is dirty (added or deleted) in that scope
   * @throws AclException if validation fails
   */
private static void calculateMasks(List<AclEntry> aclBuilder, EnumMap<AclEntryScope, AclEntry> providedMask, EnumSet<AclEntryScope> maskDirty, EnumSet<AclEntryScope> scopeDirty) throws AclException {
    EnumSet<AclEntryScope> scopeFound = EnumSet.noneOf(AclEntryScope.class);
    EnumMap<AclEntryScope, FsAction> unionPerms = Maps.newEnumMap(AclEntryScope.class);
    EnumSet<AclEntryScope> maskNeeded = EnumSet.noneOf(AclEntryScope.class);
    // union of group class permissions in each scope.
    for (AclEntry entry : aclBuilder) {
        scopeFound.add(entry.getScope());
        if (entry.getType() == GROUP || entry.getName() != null) {
            FsAction scopeUnionPerms = Objects.firstNonNull(unionPerms.get(entry.getScope()), FsAction.NONE);
            unionPerms.put(entry.getScope(), scopeUnionPerms.or(entry.getPermission()));
        }
        if (entry.getName() != null) {
            maskNeeded.add(entry.getScope());
        }
    }
    // Add mask entry if needed in each scope.
    for (AclEntryScope scope : scopeFound) {
        if (!providedMask.containsKey(scope) && maskNeeded.contains(scope) && maskDirty.contains(scope)) {
            // Caller explicitly removed mask entry, but it's required.
            throw new AclException("Invalid ACL: mask is required and cannot be deleted.");
        } else if (providedMask.containsKey(scope) && (!scopeDirty.contains(scope) || maskDirty.contains(scope))) {
            // Caller explicitly provided new mask, or we are preserving the existing
            // mask in an unchanged scope.
            aclBuilder.add(providedMask.get(scope));
        } else if (maskNeeded.contains(scope) || providedMask.containsKey(scope)) {
            // Otherwise, if there are maskable entries present, or the ACL
            // previously had a mask, then recalculate a mask automatically.
            aclBuilder.add(new AclEntry.Builder().setScope(scope).setType(MASK).setPermission(unionPerms.get(scope)).build());
        }
    }
}
Also used : FsAction(org.apache.hadoop.fs.permission.FsAction) AclEntryScope(org.apache.hadoop.fs.permission.AclEntryScope) AclEntry(org.apache.hadoop.fs.permission.AclEntry) AclException(org.apache.hadoop.hdfs.protocol.AclException)

Example 3 with AclEntryScope

use of org.apache.hadoop.fs.permission.AclEntryScope in project hadoop by apache.

the class AclTransformation method replaceAclEntries.

/**
   * Completely replaces the ACL with the entries of the ACL spec.  If
   * necessary, recalculates the mask entries.  If necessary, default entries
   * are inferred by copying the permissions of the corresponding access
   * entries.  Replacement occurs separately for each of the access ACL and the
   * default ACL.  If the ACL spec contains only access entries, then the
   * existing default entries are retained.  If the ACL spec contains only
   * default entries, then the existing access entries are retained.  If the ACL
   * spec contains both access and default entries, then both are replaced.
   *
   * @param existingAcl List<AclEntry> existing ACL
   * @param inAclSpec List<AclEntry> ACL spec containing replacement entries
   * @return List<AclEntry> new ACL
   * @throws AclException if validation fails
   */
public static List<AclEntry> replaceAclEntries(List<AclEntry> existingAcl, List<AclEntry> inAclSpec) throws AclException {
    ValidatedAclSpec aclSpec = new ValidatedAclSpec(inAclSpec);
    ArrayList<AclEntry> aclBuilder = Lists.newArrayListWithCapacity(MAX_ENTRIES);
    // Replacement is done separately for each scope: access and default.
    EnumMap<AclEntryScope, AclEntry> providedMask = Maps.newEnumMap(AclEntryScope.class);
    EnumSet<AclEntryScope> maskDirty = EnumSet.noneOf(AclEntryScope.class);
    EnumSet<AclEntryScope> scopeDirty = EnumSet.noneOf(AclEntryScope.class);
    for (AclEntry aclSpecEntry : aclSpec) {
        scopeDirty.add(aclSpecEntry.getScope());
        if (aclSpecEntry.getType() == MASK) {
            providedMask.put(aclSpecEntry.getScope(), aclSpecEntry);
            maskDirty.add(aclSpecEntry.getScope());
        } else {
            aclBuilder.add(aclSpecEntry);
        }
    }
    // Copy existing entries if the scope was not replaced.
    for (AclEntry existingEntry : existingAcl) {
        if (!scopeDirty.contains(existingEntry.getScope())) {
            if (existingEntry.getType() == MASK) {
                providedMask.put(existingEntry.getScope(), existingEntry);
            } else {
                aclBuilder.add(existingEntry);
            }
        }
    }
    copyDefaultsIfNeeded(aclBuilder);
    calculateMasks(aclBuilder, providedMask, maskDirty, scopeDirty);
    return buildAndValidateAcl(aclBuilder);
}
Also used : AclEntryScope(org.apache.hadoop.fs.permission.AclEntryScope) AclEntry(org.apache.hadoop.fs.permission.AclEntry)

Example 4 with AclEntryScope

use of org.apache.hadoop.fs.permission.AclEntryScope in project hadoop by apache.

the class AclTransformation method mergeAclEntries.

/**
   * Merges the entries of the ACL spec into the existing ACL.  If necessary,
   * recalculates the mask entries.  If necessary, default entries may be
   * inferred by copying the permissions of the corresponding access entries.
   *
   * @param existingAcl List<AclEntry> existing ACL
   * @param inAclSpec List<AclEntry> ACL spec containing entries to merge
   * @return List<AclEntry> new ACL
   * @throws AclException if validation fails
   */
public static List<AclEntry> mergeAclEntries(List<AclEntry> existingAcl, List<AclEntry> inAclSpec) throws AclException {
    ValidatedAclSpec aclSpec = new ValidatedAclSpec(inAclSpec);
    ArrayList<AclEntry> aclBuilder = Lists.newArrayListWithCapacity(MAX_ENTRIES);
    List<AclEntry> foundAclSpecEntries = Lists.newArrayListWithCapacity(MAX_ENTRIES);
    EnumMap<AclEntryScope, AclEntry> providedMask = Maps.newEnumMap(AclEntryScope.class);
    EnumSet<AclEntryScope> maskDirty = EnumSet.noneOf(AclEntryScope.class);
    EnumSet<AclEntryScope> scopeDirty = EnumSet.noneOf(AclEntryScope.class);
    for (AclEntry existingEntry : existingAcl) {
        AclEntry aclSpecEntry = aclSpec.findByKey(existingEntry);
        if (aclSpecEntry != null) {
            foundAclSpecEntries.add(aclSpecEntry);
            scopeDirty.add(aclSpecEntry.getScope());
            if (aclSpecEntry.getType() == MASK) {
                providedMask.put(aclSpecEntry.getScope(), aclSpecEntry);
                maskDirty.add(aclSpecEntry.getScope());
            } else {
                aclBuilder.add(aclSpecEntry);
            }
        } else {
            if (existingEntry.getType() == MASK) {
                providedMask.put(existingEntry.getScope(), existingEntry);
            } else {
                aclBuilder.add(existingEntry);
            }
        }
    }
    // ACL spec entries that were not replacements are new additions.
    for (AclEntry newEntry : aclSpec) {
        if (Collections.binarySearch(foundAclSpecEntries, newEntry, ACL_ENTRY_COMPARATOR) < 0) {
            scopeDirty.add(newEntry.getScope());
            if (newEntry.getType() == MASK) {
                providedMask.put(newEntry.getScope(), newEntry);
                maskDirty.add(newEntry.getScope());
            } else {
                aclBuilder.add(newEntry);
            }
        }
    }
    copyDefaultsIfNeeded(aclBuilder);
    calculateMasks(aclBuilder, providedMask, maskDirty, scopeDirty);
    return buildAndValidateAcl(aclBuilder);
}
Also used : AclEntryScope(org.apache.hadoop.fs.permission.AclEntryScope) AclEntry(org.apache.hadoop.fs.permission.AclEntry)

Aggregations

AclEntry (org.apache.hadoop.fs.permission.AclEntry)4 AclEntryScope (org.apache.hadoop.fs.permission.AclEntryScope)4 FsAction (org.apache.hadoop.fs.permission.FsAction)1 AclException (org.apache.hadoop.hdfs.protocol.AclException)1