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.hbase.security.access; 019 020import java.util.Collection; 021import java.util.HashMap; 022import java.util.Map; 023import java.util.Map.Entry; 024import org.apache.hadoop.hbase.Cell; 025import org.apache.hadoop.hbase.TableName; 026import org.apache.hadoop.hbase.security.User; 027import org.apache.hadoop.hbase.util.Bytes; 028import org.apache.yetus.audience.InterfaceAudience; 029 030import org.apache.hbase.thirdparty.com.google.common.base.Joiner; 031 032/** 033 * Represents the result of an authorization check for logging and error reporting. 034 */ 035@InterfaceAudience.Private 036public class AuthResult { 037 private boolean allowed; 038 private final String namespace; 039 private final TableName table; 040 private final Permission.Action action; 041 private final String request; 042 private String reason; 043 private final User user; 044 private AuthResult.Params params; 045 046 // "family" and "qualifier" should only be used if "families" is null. 047 private final byte[] family; 048 private final byte[] qualifier; 049 private final Map<byte[], ? extends Collection<?>> families; 050 051 public AuthResult(boolean allowed, String request, String reason, User user, 052 Permission.Action action, TableName table, byte[] family, byte[] qualifier) { 053 this.allowed = allowed; 054 this.request = request; 055 this.reason = reason; 056 this.user = user; 057 this.table = table; 058 this.family = family; 059 this.qualifier = qualifier; 060 this.action = action; 061 this.families = null; 062 this.namespace = null; 063 this.params = new Params().setTableName(table).setFamily(family).setQualifier(qualifier); 064 } 065 066 public AuthResult(boolean allowed, String request, String reason, User user, 067 Permission.Action action, TableName table, Map<byte[], ? extends Collection<?>> families) { 068 this.allowed = allowed; 069 this.request = request; 070 this.reason = reason; 071 this.user = user; 072 this.table = table; 073 this.family = null; 074 this.qualifier = null; 075 this.action = action; 076 this.families = families; 077 this.namespace = null; 078 this.params = new Params().setTableName(table).setFamilies(families); 079 } 080 081 public AuthResult(boolean allowed, String request, String reason, User user, 082 Permission.Action action, String namespace) { 083 this.allowed = allowed; 084 this.request = request; 085 this.reason = reason; 086 this.user = user; 087 this.namespace = namespace; 088 this.action = action; 089 this.table = null; 090 this.family = null; 091 this.qualifier = null; 092 this.families = null; 093 this.params = new Params().setNamespace(namespace); 094 } 095 096 public boolean isAllowed() { 097 return allowed; 098 } 099 100 public User getUser() { 101 return user; 102 } 103 104 public String getReason() { 105 return reason; 106 } 107 108 public TableName getTableName() { 109 return table; 110 } 111 112 public byte[] getFamily() { 113 return family; 114 } 115 116 public byte[] getQualifier() { 117 return qualifier; 118 } 119 120 public Permission.Action getAction() { 121 return action; 122 } 123 124 public String getRequest() { 125 return request; 126 } 127 128 public Params getParams() { 129 return this.params; 130 } 131 132 public void setAllowed(boolean allowed) { 133 this.allowed = allowed; 134 } 135 136 public void setReason(String reason) { 137 this.reason = reason; 138 } 139 140 private static String toFamiliesString(Map<byte[], ? extends Collection<?>> families, 141 byte[] family, byte[] qual) { 142 StringBuilder sb = new StringBuilder(); 143 if (families != null) { 144 boolean first = true; 145 for (Map.Entry<byte[], ? extends Collection<?>> entry : families.entrySet()) { 146 String familyName = Bytes.toString(entry.getKey()); 147 if (entry.getValue() != null && !entry.getValue().isEmpty()) { 148 for (Object o : entry.getValue()) { 149 String qualifier; 150 if (o instanceof byte[]) { 151 qualifier = Bytes.toString((byte[]) o); 152 } else if (o instanceof Cell) { 153 Cell c = (Cell) o; 154 qualifier = Bytes.toString(c.getQualifierArray(), c.getQualifierOffset(), 155 c.getQualifierLength()); 156 } else { 157 // Shouldn't really reach this? 158 qualifier = o.toString(); 159 } 160 if (!first) { 161 sb.append("|"); 162 } 163 first = false; 164 sb.append(familyName).append(":").append(qualifier); 165 } 166 } else { 167 if (!first) { 168 sb.append("|"); 169 } 170 first = false; 171 sb.append(familyName); 172 } 173 } 174 } else if (family != null) { 175 sb.append(Bytes.toString(family)); 176 if (qual != null) { 177 sb.append(":").append(Bytes.toString(qual)); 178 } 179 } 180 return sb.toString(); 181 } 182 183 public String toContextString() { 184 StringBuilder sb = new StringBuilder(); 185 String familiesString = toFamiliesString(families, family, qualifier); 186 sb.append("(user=").append(user != null ? user.getName() : "UNKNOWN").append(", "); 187 sb.append("scope=") 188 .append(namespace != null ? namespace 189 : table == null ? "GLOBAL" 190 : table.getNameWithNamespaceInclAsString()) 191 .append(", "); 192 if (namespace == null && familiesString.length() > 0) { 193 sb.append("family=").append(familiesString).append(", "); 194 } 195 String paramsString = params.toString(); 196 if (paramsString.length() > 0) { 197 sb.append("params=[").append(paramsString).append("],"); 198 } 199 sb.append("action=").append(action != null ? action.toString() : "").append(")"); 200 return sb.toString(); 201 } 202 203 @Override 204 public String toString() { 205 return "AuthResult" + toContextString(); 206 } 207 208 public static AuthResult allow(String request, String reason, User user, Permission.Action action, 209 String namespace) { 210 return new AuthResult(true, request, reason, user, action, namespace); 211 } 212 213 public static AuthResult allow(String request, String reason, User user, Permission.Action action, 214 TableName table, byte[] family, byte[] qualifier) { 215 return new AuthResult(true, request, reason, user, action, table, family, qualifier); 216 } 217 218 public static AuthResult allow(String request, String reason, User user, Permission.Action action, 219 TableName table, Map<byte[], ? extends Collection<?>> families) { 220 return new AuthResult(true, request, reason, user, action, table, families); 221 } 222 223 public static AuthResult deny(String request, String reason, User user, Permission.Action action, 224 String namespace) { 225 return new AuthResult(false, request, reason, user, action, namespace); 226 } 227 228 public static AuthResult deny(String request, String reason, User user, Permission.Action action, 229 TableName table, byte[] family, byte[] qualifier) { 230 return new AuthResult(false, request, reason, user, action, table, family, qualifier); 231 } 232 233 public static AuthResult deny(String request, String reason, User user, Permission.Action action, 234 TableName table, Map<byte[], ? extends Collection<?>> families) { 235 return new AuthResult(false, request, reason, user, action, table, families); 236 } 237 238 public String toFamilyString() { 239 return toFamiliesString(families, family, qualifier); 240 } 241 242 public static class Params { 243 private String namespace = null; 244 private TableName tableName = null; 245 private Map<byte[], ? extends Collection<?>> families = null; 246 byte[] family = null; 247 byte[] qualifier = null; 248 // For extra parameters to be shown in audit log 249 private final Map<String, String> extraParams = new HashMap<String, String>(2); 250 251 public Params addExtraParam(String key, String value) { 252 extraParams.put(key, value); 253 return this; 254 } 255 256 public Params setNamespace(String namespace) { 257 this.namespace = namespace; 258 return this; 259 } 260 261 public Params setTableName(TableName table) { 262 this.tableName = table; 263 return this; 264 } 265 266 public Params setFamilies(Map<byte[], ? extends Collection<?>> families) { 267 this.families = families; 268 return this; 269 } 270 271 public Params setFamily(byte[] family) { 272 this.family = family; 273 return this; 274 } 275 276 public Params setQualifier(byte[] qualifier) { 277 this.qualifier = qualifier; 278 return this; 279 } 280 281 @Override 282 public String toString() { 283 String familiesString = toFamiliesString(families, family, qualifier); 284 String[] params = new String[] { namespace != null ? "namespace=" + namespace : null, 285 tableName != null ? "table=" + tableName.getNameWithNamespaceInclAsString() : null, 286 familiesString.length() > 0 ? "family=" + familiesString : null, 287 extraParams.isEmpty() ? null : concatenateExtraParams() }; 288 return Joiner.on(",").skipNulls().join(params); 289 } 290 291 /** Returns extra parameter key/value string */ 292 private String concatenateExtraParams() { 293 final StringBuilder sb = new StringBuilder(); 294 boolean first = true; 295 for (Entry<String, String> entry : extraParams.entrySet()) { 296 if (entry.getKey() != null && entry.getValue() != null) { 297 if (!first) { 298 sb.append(','); 299 } 300 first = false; 301 sb.append(entry.getKey() + '='); 302 sb.append(entry.getValue()); 303 } 304 } 305 return sb.toString(); 306 } 307 } 308}