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.hdfs.DFSUtil; 033import org.apache.hadoop.security.AccessControlException; 034import org.apache.hadoop.security.UserGroupInformation; 035 036@InterfaceAudience.Public 037@InterfaceStability.Unstable 038public abstract class INodeAttributeProvider { 039 040 /** 041 * The AccessControlEnforcer allows implementations to override the 042 * default File System permission checking logic enforced on a file system 043 * object 044 */ 045 public interface AccessControlEnforcer { 046 047 /** 048 * Checks permission on a file system object. Has to throw an Exception 049 * if the filesystem object is not accessessible by the calling Ugi. 050 * @param fsOwner Filesystem owner (The Namenode user) 051 * @param supergroup super user geoup 052 * @param callerUgi UserGroupInformation of the caller 053 * @param inodeAttrs Array of INode attributes for each path element in the 054 * the path 055 * @param inodes Array of INodes for each path element in the path 056 * @param pathByNameArr Array of byte arrays of the LocalName 057 * @param snapshotId the snapshotId of the requested path 058 * @param path Path String 059 * @param ancestorIndex Index of ancestor 060 * @param doCheckOwner perform ownership check 061 * @param ancestorAccess The access required by the ancestor of the path. 062 * @param parentAccess The access required by the parent of the path. 063 * @param access The access required by the path. 064 * @param subAccess If path is a directory, It is the access required of 065 * the path and all the sub-directories. If path is not a 066 * directory, there should ideally be no effect. 067 * @param ignoreEmptyDir Ignore permission checking for empty directory? 068 * @throws AccessControlException 069 */ 070 public abstract void checkPermission(String fsOwner, String supergroup, 071 UserGroupInformation callerUgi, INodeAttributes[] inodeAttrs, 072 INode[] inodes, byte[][] pathByNameArr, int snapshotId, String path, 073 int ancestorIndex, boolean doCheckOwner, FsAction ancestorAccess, 074 FsAction parentAccess, FsAction access, FsAction subAccess, 075 boolean ignoreEmptyDir) 076 throws AccessControlException; 077 078 } 079 /** 080 * Initialize the provider. This method is called at NameNode startup 081 * time. 082 */ 083 public abstract void start(); 084 085 /** 086 * Shutdown the provider. This method is called at NameNode shutdown time. 087 */ 088 public abstract void stop(); 089 090 @VisibleForTesting 091 String[] getPathElements(String path) { 092 path = path.trim(); 093 if (path.charAt(0) != Path.SEPARATOR_CHAR) { 094 throw new IllegalArgumentException("It must be an absolute path: " + 095 path); 096 } 097 int numOfElements = StringUtils.countMatches(path, Path.SEPARATOR); 098 if (path.length() > 1 && path.endsWith(Path.SEPARATOR)) { 099 numOfElements--; 100 } 101 String[] pathElements = new String[numOfElements]; 102 int elementIdx = 0; 103 int idx = 0; 104 int found = path.indexOf(Path.SEPARATOR_CHAR, idx); 105 while (found > -1) { 106 if (found > idx) { 107 pathElements[elementIdx++] = path.substring(idx, found); 108 } 109 idx = found + 1; 110 found = path.indexOf(Path.SEPARATOR_CHAR, idx); 111 } 112 if (idx < path.length()) { 113 pathElements[elementIdx] = path.substring(idx); 114 } 115 return pathElements; 116 } 117 118 public INodeAttributes getAttributes(String fullPath, INodeAttributes inode) { 119 return getAttributes(getPathElements(fullPath), inode); 120 } 121 122 public abstract INodeAttributes getAttributes(String[] pathElements, 123 INodeAttributes inode); 124 125 public INodeAttributes getAttributes(byte[][] components, 126 INodeAttributes inode) { 127 String[] elements = new String[components.length]; 128 for (int i = 0; i < elements.length; i++) { 129 elements[i] = DFSUtil.bytes2String(components[i]); 130 } 131 return getAttributes(elements, inode); 132 } 133 134 /** 135 * Can be over-ridden by implementations to provide a custom Access Control 136 * Enforcer that can provide an alternate implementation of the 137 * default permission checking logic. 138 * @param defaultEnforcer The Default AccessControlEnforcer 139 * @return The AccessControlEnforcer to use 140 */ 141 public AccessControlEnforcer getExternalAccessControlEnforcer( 142 AccessControlEnforcer defaultEnforcer) { 143 return defaultEnforcer; 144 } 145}