001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * 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.apache.hadoop.hdfs.server.namenode; 019 020import java.util.Arrays; 021import java.util.Collections; 022import java.util.HashSet; 023import java.util.Set; 024 025import com.google.common.annotations.VisibleForTesting; 026 027import org.apache.commons.lang.StringUtils; 028import org.apache.hadoop.classification.InterfaceAudience; 029import org.apache.hadoop.classification.InterfaceStability; 030import org.apache.hadoop.fs.Path; 031import org.apache.hadoop.fs.permission.FsAction; 032import org.apache.hadoop.security.AccessControlException; 033import org.apache.hadoop.security.UserGroupInformation; 034 035@InterfaceAudience.Public 036@InterfaceStability.Unstable 037public abstract class INodeAttributeProvider { 038 039 /** 040 * The AccessControlEnforcer allows implementations to override the 041 * default File System permission checking logic enforced on a file system 042 * object 043 */ 044 public interface AccessControlEnforcer { 045 046 /** 047 * Checks permission on a file system object. Has to throw an Exception 048 * if the filesystem object is not accessessible by the calling Ugi. 049 * @param fsOwner Filesystem owner (The Namenode user) 050 * @param supergroup super user geoup 051 * @param callerUgi UserGroupInformation of the caller 052 * @param inodeAttrs Array of INode attributes for each path element in the 053 * the path 054 * @param inodes Array of INodes for each path element in the path 055 * @param pathByNameArr Array of byte arrays of the LocalName 056 * @param snapshotId the snapshotId of the requested path 057 * @param path Path String 058 * @param ancestorIndex Index of ancestor 059 * @param doCheckOwner perform ownership check 060 * @param ancestorAccess The access required by the ancestor of the path. 061 * @param parentAccess The access required by the parent of the path. 062 * @param access The access required by the path. 063 * @param subAccess If path is a directory, It is the access required of 064 * the path and all the sub-directories. If path is not a 065 * directory, there should ideally be no effect. 066 * @param ignoreEmptyDir Ignore permission checking for empty directory? 067 * @throws AccessControlException 068 */ 069 public abstract void checkPermission(String fsOwner, String supergroup, 070 UserGroupInformation callerUgi, INodeAttributes[] inodeAttrs, 071 INode[] inodes, byte[][] pathByNameArr, int snapshotId, String path, 072 int ancestorIndex, boolean doCheckOwner, FsAction ancestorAccess, 073 FsAction parentAccess, FsAction access, FsAction subAccess, 074 boolean ignoreEmptyDir) 075 throws AccessControlException; 076 077 } 078 /** 079 * Initialize the provider. This method is called at NameNode startup 080 * time. 081 */ 082 public abstract void start(); 083 084 /** 085 * Shutdown the provider. This method is called at NameNode shutdown time. 086 */ 087 public abstract void stop(); 088 089 @VisibleForTesting 090 String[] getPathElements(String path) { 091 path = path.trim(); 092 if (path.charAt(0) != Path.SEPARATOR_CHAR) { 093 throw new IllegalArgumentException("It must be an absolute path: " + 094 path); 095 } 096 int numOfElements = StringUtils.countMatches(path, Path.SEPARATOR); 097 if (path.length() > 1 && path.endsWith(Path.SEPARATOR)) { 098 numOfElements--; 099 } 100 String[] pathElements = new String[numOfElements]; 101 int elementIdx = 0; 102 int idx = 0; 103 int found = path.indexOf(Path.SEPARATOR_CHAR, idx); 104 while (found > -1) { 105 if (found > idx) { 106 pathElements[elementIdx++] = path.substring(idx, found); 107 } 108 idx = found + 1; 109 found = path.indexOf(Path.SEPARATOR_CHAR, idx); 110 } 111 if (idx < path.length()) { 112 pathElements[elementIdx] = path.substring(idx); 113 } 114 return pathElements; 115 } 116 117 public INodeAttributes getAttributes(String fullPath, INodeAttributes inode) { 118 return getAttributes(getPathElements(fullPath), inode); 119 } 120 121 public abstract INodeAttributes getAttributes(String[] pathElements, 122 INodeAttributes inode); 123 124 /** 125 * Can be over-ridden by implementations to provide a custom Access Control 126 * Enforcer that can provide an alternate implementation of the 127 * default permission checking logic. 128 * @param defaultEnforcer The Default AccessControlEnforcer 129 * @return The AccessControlEnforcer to use 130 */ 131 public AccessControlEnforcer getExternalAccessControlEnforcer( 132 AccessControlEnforcer defaultEnforcer) { 133 return defaultEnforcer; 134 } 135}